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
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
);
43 static const HklFunction bissector_func
= {
44 .function
= _bissector_func
,
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
,
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
,
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
,
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
,
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
,
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
,
132 return hkl_mode_auto_new(&info
,
133 &psi_constant_vertical_mode_operations
,
137 /***********************/
138 /* pseudo axes engines */
139 /***********************/
141 static HklEngine
*hkl_engine_e4c_hkl_new(void)
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());
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)
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
);
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" \
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" \
203 "+ 1 axis for the detector\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
);
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);
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());
236 REGISTER_DIFFRACTOMETER(eulerian4C_vertical
, "E4CV", HKL_GEOMETRY_EULERIAN4C_VERTICAL_DESCRIPTION
);
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" \
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" \
251 "+ 1 axis for the detector\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
);
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);
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());
284 REGISTER_DIFFRACTOMETER(soleil_mars
, "SOLEIL MARS", HKL_GEOMETRY_TYPE_SOLEIL_MARS_DESCRIPTION
);
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" \
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" \
298 "+ 1 axis for the detector\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
);
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);
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());
331 REGISTER_DIFFRACTOMETER(eulerian4C_horizontal
, "E4CH", HKL_GEOMETRY_TYPE_EULERIAN4C_HORIZONTAL_DESCRIPTION
);