[hkl] factorize the double_diffraction_parameters (with description)
[hkl.git] / hkl / hkl-engine-e4c.c
blob023215d8ee92f9a95a8295ab7517475d2a4836f1
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-q-private.h" // for hkl_engine_q2_new, etc
25 #include "hkl-pseudoaxis-common-hkl-private.h" // for hkl_mode_operations, etc
26 #include "hkl-pseudoaxis-common-psi-private.h" // for hkl_engine_psi_new, etc
28 /* bissector */
30 static int _bissector_func(const gsl_vector *x, void *params, gsl_vector *f)
32 const double omega = x->data[0];
33 const double tth = x->data[3];
35 CHECK_NAN(x->data, x->size);
37 RUBh_minus_Q(x->data, params, f->data);
38 f->data[3] = tth - 2 * fmod(omega,M_PI);
40 return GSL_SUCCESS;
43 static const HklFunction bissector_func = {
44 .function = _bissector_func,
45 .size = 4,
48 static HklMode *bissector(void)
50 static const char* axes[] = {"omega", "chi", "phi", "tth"};
51 static const HklFunction *functions[] = {&bissector_func};
52 static const HklModeAutoInfo info = {
53 HKL_MODE_AUTO_INFO(__func__, axes, axes, functions),
56 return hkl_mode_auto_new(&info,
57 &hkl_mode_operations,
58 TRUE);
61 static HklMode *constant_omega(void)
63 static const char* axes_r[] = {"omega", "chi", "phi", "tth"};
64 static const char* axes_w[] = {"chi", "phi", "tth"};
65 static const HklFunction *functions[] = {&RUBh_minus_Q_func};
66 static const HklModeAutoInfo info = {
67 HKL_MODE_AUTO_INFO(__func__, axes_r, axes_w, functions),
70 return hkl_mode_auto_new(&info,
71 &hkl_mode_operations,
72 TRUE);
75 static HklMode *constant_chi(void)
77 static const char* axes_r[] = {"omega", "chi", "phi", "tth"};
78 static const char* axes_w[] = {"omega", "phi", "tth"};
79 static const HklFunction *functions[] = {&RUBh_minus_Q_func};
80 static const HklModeAutoInfo info = {
81 HKL_MODE_AUTO_INFO(__func__, axes_r, axes_w, functions),
84 return hkl_mode_auto_new(&info,
85 &hkl_mode_operations,
86 TRUE);
89 static HklMode *constant_phi(void)
91 static const char* axes_r[] = {"omega", "chi", "phi", "tth"};
92 static const char* axes_w[] = {"omega", "chi", "tth"};
93 static const HklFunction *functions[] = {&RUBh_minus_Q_func};
94 static const HklModeAutoInfo info = {
95 HKL_MODE_AUTO_INFO(__func__, axes_r, axes_w, functions),
98 return hkl_mode_auto_new(&info,
99 &hkl_mode_operations,
100 TRUE);
103 static HklMode *double_diffraction(void)
105 static const char* axes[] = {"omega", "chi", "phi", "tth"};
106 static const HklFunction *functions[] = {&double_diffraction_func};
107 static const HklModeAutoInfo info = {
108 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
109 functions, double_diffraction_parameters),
112 return hkl_mode_auto_new(&info,
113 &hkl_mode_operations,
114 TRUE);
117 static HklMode *psi_constant(void)
119 static const char* axes[] = {"omega", "chi", "phi", "tth"};
120 static const HklFunction *functions[] = {&psi_constant_vertical_func};
121 static const HklParameter parameters[] = {
122 {HKL_PARAMETER_DEFAULTS, .name = "h2", .range = {.min=-1, .max=1}, ._value = 1,},
123 {HKL_PARAMETER_DEFAULTS, .name = "k2", .range = {.min=-1, .max=1}, ._value = 1,},
124 {HKL_PARAMETER_DEFAULTS, .name = "l2", .range = {.min=-1, .max=1}, ._value = 1,},
125 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "psi"},
127 static const HklModeAutoInfo info = {
128 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes, functions,
129 parameters),
132 return hkl_mode_auto_new(&info,
133 &psi_constant_vertical_mode_operations,
134 TRUE);
137 /***********************/
138 /* pseudo axes engines */
139 /***********************/
141 static HklEngine *hkl_engine_e4c_hkl_new(void)
143 HklEngine *self;
144 HklMode *default_mode;
146 self = hkl_engine_hkl_new();
148 default_mode = bissector();
149 hkl_engine_add_mode(self, default_mode);
150 hkl_engine_mode_set(self, default_mode);
152 hkl_engine_add_mode(self, constant_omega());
153 hkl_engine_add_mode(self, constant_chi());
154 hkl_engine_add_mode(self, constant_phi());
155 hkl_engine_add_mode(self, double_diffraction());
156 hkl_engine_add_mode(self, psi_constant());
158 return self;
161 static HklMode *psi(void)
163 static const char *axes[] = {"omega", "chi", "phi", "tth"};
164 static const HklFunction *functions[] = {&psi_func};
165 static const HklParameter parameters[] = {
166 {HKL_PARAMETER_DEFAULTS, .name = "h1", .range = {.min=-1, .max=1}, ._value=1,},
167 {HKL_PARAMETER_DEFAULTS, .name = "k1", .range = {.min=-1, .max=1}, ._value=1,},
168 {HKL_PARAMETER_DEFAULTS, .name = "l1", .range = {.min=-1, .max=1}, ._value=1,},
170 static const HklModeAutoInfo info = {
171 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes, functions, parameters),
174 return hkl_mode_psi_new(&info);
177 static HklEngine *hkl_engine_e4c_psi_new(void)
179 HklEngine *self;
180 HklMode *default_mode;
182 self = hkl_engine_psi_new();
184 default_mode = psi();
185 hkl_engine_add_mode(self, default_mode);
186 hkl_engine_mode_set(self, default_mode);
188 return self;
191 /********/
192 /* E4CV */
193 /********/
195 #define HKL_GEOMETRY_EULERIAN4C_VERTICAL_DESCRIPTION \
196 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
197 "+ 3 axes for the sample\n" \
198 "\n" \
199 " + **omega** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
200 " + **chi** : rotating around the :math:`\\vec{x}` direction (1, 0, 0)\n" \
201 " + **phi** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
202 "\n" \
203 "+ 1 axis for the detector\n" \
204 "\n" \
205 " + **tth** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n"
207 static const char* hkl_geometry_eulerian4C_vertical_axes[] = {"omega", "chi", "phi", "tth"};
209 static HklGeometry *hkl_geometry_new_eulerian4C_vertical(const HklFactory *factory)
211 HklGeometry *self = hkl_geometry_new(factory);
212 HklHolder *h;
214 h = hkl_geometry_add_holder(self);
215 hkl_holder_add_rotation_axis(h, "omega", 0, -1, 0);
216 hkl_holder_add_rotation_axis(h, "chi", 1, 0, 0);
217 hkl_holder_add_rotation_axis(h, "phi", 0, -1, 0);
219 h = hkl_geometry_add_holder(self);
220 hkl_holder_add_rotation_axis(h, "tth", 0, -1, 0);
222 return self;
225 static HklEngineList *hkl_engine_list_new_eulerian4C_vertical(const HklFactory *factory)
227 HklEngineList *self = hkl_engine_list_new();
229 hkl_engine_list_add(self, hkl_engine_e4c_hkl_new());
230 hkl_engine_list_add(self, hkl_engine_e4c_psi_new());
231 hkl_engine_list_add(self, hkl_engine_q_new());
233 return self;
236 REGISTER_DIFFRACTOMETER(eulerian4C_vertical, "E4CV", HKL_GEOMETRY_EULERIAN4C_VERTICAL_DESCRIPTION);
239 /***************/
240 /* SOLEIL MARS */
241 /***************/
243 #define HKL_GEOMETRY_TYPE_SOLEIL_MARS_DESCRIPTION \
244 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
245 "+ 3 axes for the sample\n" \
246 "\n" \
247 " + **omega** : rotating around the :math:`\\vec{z}` direction (0, -1, 0)\n" \
248 " + **chi** : rotating around the :math:`\\vec{x}` direction (-1, 0, 0)\n" \
249 " + **phi** : rotating around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
250 "\n" \
251 "+ 1 axis for the detector\n" \
252 "\n" \
253 " + **tth** : rotation around the :math:`\\vec{z}` direction (0, -1, 0)\n"
255 static const char* hkl_geometry_soleil_mars_axes[] = {"omega", "chi", "phi", "tth"};
257 static HklGeometry *hkl_geometry_new_soleil_mars(const HklFactory *factory)
259 HklGeometry *self = hkl_geometry_new(factory);
260 HklHolder *h;
262 h = hkl_geometry_add_holder(self);
263 hkl_holder_add_rotation_axis(h, "omega", 0, -1, 0);
264 hkl_holder_add_rotation_axis(h, "chi", -1, 0, 0);
265 hkl_holder_add_rotation_axis(h, "phi", 0, 0, 1);
267 h = hkl_geometry_add_holder(self);
268 hkl_holder_add_rotation_axis(h, "tth", 0, -1, 0);
270 return self;
273 static HklEngineList *hkl_engine_list_new_soleil_mars(const HklFactory *factory)
275 HklEngineList *self = hkl_engine_list_new();
277 hkl_engine_list_add(self, hkl_engine_e4c_hkl_new());
278 hkl_engine_list_add(self, hkl_engine_e4c_psi_new());
279 hkl_engine_list_add(self, hkl_engine_q_new());
281 return self;
284 REGISTER_DIFFRACTOMETER(soleil_mars, "SOLEIL MARS", HKL_GEOMETRY_TYPE_SOLEIL_MARS_DESCRIPTION);
286 /********/
287 /* E4CH */
288 /********/
290 #define HKL_GEOMETRY_TYPE_EULERIAN4C_HORIZONTAL_DESCRIPTION \
291 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
292 "+ 3 axes for the sample\n" \
293 "\n" \
294 " + **omega** : rotating around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
295 " + **chi** : rotating around the :math:`\\vec{x}` direction (1, 0, 0)\n" \
296 " + **phi** : rotating around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
297 "\n" \
298 "+ 1 axis for the detector\n" \
299 "\n" \
300 " + **tth** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n"
302 static const char* hkl_geometry_eulerian4C_horizontal_axes[] = {"omega", "chi", "phi", "tth"};
304 static HklGeometry *hkl_geometry_new_eulerian4C_horizontal(const HklFactory *factory)
306 HklGeometry *self = hkl_geometry_new(factory);
307 HklHolder *h;
309 h = hkl_geometry_add_holder(self);
310 hkl_holder_add_rotation_axis(h, "omega", 0, 0, 1);
311 hkl_holder_add_rotation_axis(h, "chi", 1, 0, 0);
312 hkl_holder_add_rotation_axis(h, "phi", 0, 0, 1);
314 h = hkl_geometry_add_holder(self);
315 hkl_holder_add_rotation_axis(h, "tth", 0, 0, 1);
317 return self;
320 static HklEngineList *hkl_engine_list_new_eulerian4C_horizontal(const HklFactory *factory)
322 HklEngineList *self = hkl_engine_list_new();
324 hkl_engine_list_add(self, hkl_engine_e4c_hkl_new());
325 hkl_engine_list_add(self, hkl_engine_e4c_psi_new());
326 hkl_engine_list_add(self, hkl_engine_q_new());
328 return self;
331 REGISTER_DIFFRACTOMETER(eulerian4C_horizontal, "E4CH", HKL_GEOMETRY_TYPE_EULERIAN4C_HORIZONTAL_DESCRIPTION);