[contrib] factorize the [Double] -> [Angle Double] transformation
[hkl.git] / hkl / hkl-engine-k4c.c
blob82d2c3a670cae176a53ddfbc8691d3e73c494ff1
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-2014 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
29 static void hkl_geometry_list_multiply_k4c_real(HklGeometryList *self,
30 HklGeometryListItem *item)
32 HklGeometry *geometry;
33 HklGeometry *copy;
34 double komega, komegap;
35 double kappa, kappap;
36 double kphi, kphip;
38 geometry = item->geometry;
39 komega = hkl_parameter_value_get(darray_item(geometry->axes, 0), HKL_UNIT_DEFAULT);
40 kappa = hkl_parameter_value_get(darray_item(geometry->axes, 1), HKL_UNIT_DEFAULT);
41 kphi = hkl_parameter_value_get(darray_item(geometry->axes, 2), HKL_UNIT_DEFAULT);
43 kappa_2_kappap(komega, kappa, kphi, 50 * HKL_DEGTORAD, &komegap, &kappap, &kphip);
45 copy = hkl_geometry_new_copy(geometry);
46 /* TODO parameter list for the geometry */
47 hkl_parameter_value_set(darray_item(copy->axes, 0), komegap, HKL_UNIT_DEFAULT, NULL);
48 hkl_parameter_value_set(darray_item(copy->axes, 1), kappap, HKL_UNIT_DEFAULT, NULL);
49 hkl_parameter_value_set(darray_item(copy->axes, 2), kphip, HKL_UNIT_DEFAULT, NULL);
51 hkl_geometry_update(copy);
52 hkl_geometry_list_add(self, copy);
53 hkl_geometry_free(copy);
56 /************/
57 /* hkl mode */
58 /************/
60 /* bissector */
62 static int _bissector_f1(const gsl_vector *x, void *params, gsl_vector *f)
64 const double komega = x->data[0];
65 const double kappa = x->data[1];
66 const double tth = x->data[3];
67 double omega;
69 CHECK_NAN(x->data, x->size);
71 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
73 RUBh_minus_Q(x->data, params, f->data);
74 f->data[3] = fmod(tth - 2 * fmod(omega, M_PI), 2*M_PI);
76 return GSL_SUCCESS;
79 static const HklFunction bissector_f1 = {
80 .function = _bissector_f1,
81 .size = 4,
84 static int _bissector_f2(const gsl_vector *x, void *params, gsl_vector *f)
86 const double komega = x->data[0];
87 const double kappa = x->data[1];
88 const double tth = x->data[3];
89 double omega;
91 CHECK_NAN(x->data, x->size);
93 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
95 RUBh_minus_Q(x->data, params, f->data);
96 f->data[3] = fmod(tth - 2 * fmod(omega, M_PI), 2*M_PI);
98 return GSL_SUCCESS;
101 static const HklFunction bissector_f2 = {
102 .function = _bissector_f2,
103 .size = 4,
106 static HklMode *bissector(void)
108 static const char* axes[] = {"komega", "kappa", "kphi", "tth"};
109 static const HklFunction *functions[] = {&bissector_f1, &bissector_f2};
110 static const HklModeAutoInfo info = {
111 HKL_MODE_AUTO_INFO(__func__, axes, axes, functions),
114 return hkl_mode_auto_new(&info,
115 &hkl_mode_operations,
116 TRUE);
119 /* constant omega */
121 static int _constant_omega_f1(const gsl_vector *x, void *params, gsl_vector *f)
123 double const komega = x->data[0];
124 double const kappa = x->data[1];
125 double omega;
126 HklEngine *engine = params;
127 double omega0 = darray_item(engine->mode->parameters, 0)->_value;
129 CHECK_NAN(x->data, x->size);
131 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
133 RUBh_minus_Q(x->data, params, f->data);
134 f->data[3] = omega0 - omega;
136 return GSL_SUCCESS;
139 static const HklFunction constant_omega_f1 = {
140 .function = _constant_omega_f1,
141 .size = 4,
144 static int _constant_omega_f2(const gsl_vector *x, void *params, gsl_vector *f)
146 const double komega = x->data[0];
147 const double kappa = x->data[1];
148 double omega;
149 HklEngine *engine = params;
150 double omega0 = darray_item(engine->mode->parameters, 0)->_value;
152 CHECK_NAN(x->data, x->size);
154 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
156 RUBh_minus_Q(x->data, params, f->data);
157 f->data[3] = omega0 - omega;
159 return GSL_SUCCESS;
162 static const HklFunction constant_omega_f2 = {
163 .function = _constant_omega_f2,
164 .size = 4,
167 static HklMode *constant_omega(void)
169 static const char* axes[] = {"komega", "kappa", "kphi", "tth"};
170 static const HklFunction *functions[] = {&constant_omega_f1, &constant_omega_f2};
171 static const HklModeAutoInfo info = {
172 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
173 functions, constant_omega_parameters),
176 return hkl_mode_auto_new(&info,
177 &hkl_mode_operations,
178 TRUE);
181 /* constant chi */
183 static int _constant_chi_f1(const gsl_vector *x, void *params, gsl_vector *f)
185 const double kappa = x->data[1];
186 double chi;
187 HklEngine *engine = params;
188 double chi0 = darray_item(engine->mode->parameters, 0)->_value;
190 CHECK_NAN(x->data, x->size);
192 chi = 2 * asin(sin(kappa/2.) * sin(50 * HKL_DEGTORAD));
194 RUBh_minus_Q(x->data, params, f->data);
195 f->data[3] = chi0 - chi;
197 return GSL_SUCCESS;
200 static const HklFunction constant_chi_f1 = {
201 .function = _constant_chi_f1,
202 .size = 4,
205 static int _constant_chi_f2(const gsl_vector *x, void *params, gsl_vector *f)
207 const double kappa = x->data[1];
208 double chi;
209 HklEngine *engine = params;
210 double chi0 = darray_item(engine->mode->parameters, 0)->_value;
212 CHECK_NAN(x->data, x->size);
214 chi = -2 * asin(sin(kappa/2.) * sin(50 * HKL_DEGTORAD));
216 RUBh_minus_Q(x->data, params, f->data);
217 f->data[3] = chi0 - chi;
219 return GSL_SUCCESS;
222 static const HklFunction constant_chi_f2 = {
223 .function = _constant_chi_f2,
224 .size = 4,
227 static HklMode *constant_chi(void)
229 static const char* axes[] = {"komega", "kappa", "kphi", "tth"};
230 static const HklFunction *functions[] = {&constant_chi_f1, &constant_chi_f2};
231 static const HklModeAutoInfo info = {
232 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
233 functions, constant_chi_parameters),
236 return hkl_mode_auto_new(&info,
237 &hkl_mode_operations,
238 TRUE);
241 /* constant phi */
243 static int _constant_phi_f1(const gsl_vector *x, void *params, gsl_vector *f)
245 const double kappa = x->data[1];
246 const double kphi = x->data[2];
247 double phi;
248 HklEngine *engine = params;
249 double phi0 = darray_item(engine->mode->parameters, 0)->_value;
251 CHECK_NAN(x->data, x->size);
253 phi = kphi + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
255 RUBh_minus_Q(x->data, params, f->data);
256 f->data[3] = phi0 - phi;
258 return GSL_SUCCESS;
261 static const HklFunction constant_phi_f1 = {
262 .function = _constant_phi_f1,
263 .size = 4,
266 static int _constant_phi_f2(const gsl_vector *x, void *params, gsl_vector *f)
268 const double kappa = x->data[1];
269 const double kphi = x->data[2];
270 double phi;
271 HklEngine *engine = params;
272 double phi0 = darray_item(engine->mode->parameters, 0)->_value;
274 CHECK_NAN(x->data, x->size);
276 phi = kphi + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
278 RUBh_minus_Q(x->data, params, f->data);
279 f->data[3] = phi0 - phi;
281 return GSL_SUCCESS;
284 static const HklFunction constant_phi_f2 = {
285 .function = _constant_phi_f2,
286 .size = 4,
289 static HklMode *constant_phi(void)
291 static const char* axes[] = {"komega", "kappa", "kphi", "tth"};
292 static const HklFunction *functions[] = {&constant_phi_f1, &constant_phi_f2};
293 static const HklModeAutoInfo info = {
294 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
295 functions, constant_phi_parameters),
298 return hkl_mode_auto_new(&info,
299 &hkl_mode_operations,
300 TRUE);
303 static HklMode *double_diffraction(void)
305 static const char* axes[] = {"komega", "kappa", "kphi", "tth"};
306 static const HklFunction *functions[] = {&double_diffraction_func};
307 static const HklModeAutoInfo info = {
308 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
309 functions, double_diffraction_parameters),
312 return hkl_mode_auto_new(&info,
313 &hkl_mode_operations,
314 TRUE);
317 static HklMode *psi_constant(void)
319 static const char* axes[] = {"komega", "kappa", "kphi", "tth"};
320 static const HklFunction *functions[] = {&psi_constant_vertical_func};
321 static const HklModeAutoInfo info = {
322 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
323 functions, psi_constant_parameters),
326 return hkl_mode_auto_new(&info,
327 &psi_constant_vertical_mode_operations,
328 TRUE);
331 static HklEngine *hkl_engine_k4cv_hkl_new(void)
333 HklEngine *self;
334 HklMode *default_mode;
336 self = hkl_engine_hkl_new();
338 default_mode = bissector();
339 hkl_engine_add_mode(self, default_mode);
340 hkl_engine_mode_set(self, default_mode);
342 hkl_engine_add_mode(self, constant_omega());
343 hkl_engine_add_mode(self, constant_chi());
344 hkl_engine_add_mode(self, constant_phi());
345 hkl_engine_add_mode(self, double_diffraction());
346 hkl_engine_add_mode(self, psi_constant());
348 return self;
351 /************/
352 /* psi mode */
353 /************/
355 /* psi */
356 static HklMode *psi()
358 static const char *axes[] = {"komega", "kappa", "kphi", "tth"};
359 static const HklFunction *functions[] = {&psi_func};
360 static const HklModeAutoInfo info = {
361 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
362 functions, psi_parameters),
365 return hkl_mode_psi_new(&info);
368 static HklEngine *hkl_engine_k4cv_psi_new(void)
370 HklEngine *self;
371 HklMode *default_mode;
373 self = hkl_engine_psi_new();
375 default_mode = psi();
376 hkl_engine_add_mode(self, default_mode);
377 hkl_engine_mode_set(self, default_mode);
379 return self;
382 /********/
383 /* K4CV */
384 /********/
386 #define HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION \
387 "For this geometry there is a special parameters called :math:`\\alpha` which is the\n" \
388 "angle between the kappa rotation axis and the :math:`\\vec{y}` direction.\n" \
389 "\n" \
390 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
391 "+ 3 axes for the sample\n" \
392 "\n" \
393 " + **komega** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
394 " + **kappa** : rotating around the :math:`\\vec{x}` direction (0, :math:`-\\cos\\alpha`, :math:`-\\sin\\alpha`)\n" \
395 " + **kphi** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
396 "\n" \
397 "+ 1 axis for the detector\n" \
398 "\n" \
399 " + **tth** : rotation around the :math:`-\\\vec{y}` direction (0, -1, 0)\n"
401 static const char* hkl_geometry_kappa4C_vertical_axes[] = {"komega", "kappa", "kphi", "tth"};
403 static HklGeometry *hkl_geometry_new_kappa4C_vertical(const HklFactory *factory)
405 HklGeometry *self = hkl_geometry_new(factory);
406 double alpha = 50 * HKL_DEGTORAD;
407 HklHolder *h;
409 h = hkl_geometry_add_holder(self);
410 hkl_holder_add_rotation_axis(h, "komega", 0, -1, 0);
411 hkl_holder_add_rotation_axis(h, "kappa", 0, -cos(alpha), -sin(alpha));
412 hkl_holder_add_rotation_axis(h, "kphi", 0, -1, 0);
414 h = hkl_geometry_add_holder(self);
415 hkl_holder_add_rotation_axis(h, "tth", 0, -1, 0);
417 return self;
420 static HklEngineList *hkl_engine_list_new_kappa4C_vertical(const HklFactory *factory)
422 HklEngineList *self = hkl_engine_list_new();
424 self->geometries->multiply = hkl_geometry_list_multiply_k4c_real;
425 hkl_engine_list_add(self, hkl_engine_k4cv_hkl_new());
426 hkl_engine_list_add(self, hkl_engine_eulerians_new());
427 hkl_engine_list_add(self, hkl_engine_k4cv_psi_new());
428 hkl_engine_list_add(self, hkl_engine_q_new());
430 return self;
433 REGISTER_DIFFRACTOMETER(kappa4C_vertical, "K4CV", HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION);