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>
27 #include <ccan/array_size/array_size.h>
29 #include "hkl-pseudoaxis-auto-private.h"
30 #include "hkl-pseudoaxis-common-hkl-private.h"
32 /***********************/
33 /* numerical functions */
34 /***********************/
36 static int _bissector_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
38 const double komega
= x
->data
[0];
39 const double kappa
= x
->data
[1];
40 const double tth
= x
->data
[3];
43 CHECK_NAN(x
->data
, x
->size
);
45 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) + M_PI_2
;
47 RUBh_minus_Q(x
->data
, params
, f
->data
);
48 f
->data
[3] = fmod(tth
- 2 * fmod(omega
, M_PI
), 2*M_PI
);
53 static const HklFunction bissector_f1
= {
54 .function
= _bissector_f1
,
58 static int _bissector_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
60 const double komega
= x
->data
[0];
61 const double kappa
= x
->data
[1];
62 const double tth
= x
->data
[3];
65 CHECK_NAN(x
->data
, x
->size
);
67 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) - M_PI_2
;
69 RUBh_minus_Q(x
->data
, params
, f
->data
);
70 f
->data
[3] = fmod(tth
- 2 * fmod(omega
, M_PI
), 2*M_PI
);
75 static const HklFunction bissector_f2
= {
76 .function
= _bissector_f2
,
80 static int _constant_omega_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
82 double const komega
= x
->data
[0];
83 double const kappa
= x
->data
[1];
85 HklPseudoAxisEngine
*engine
= params
;
86 double omega0
= engine
->mode
->parameters
[0].value
;
88 CHECK_NAN(x
->data
, x
->size
);
90 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) - M_PI_2
;
92 RUBh_minus_Q(x
->data
, params
, f
->data
);
93 f
->data
[3] = omega0
- omega
;
98 static const HklFunction constant_omega_f1
= {
99 .function
= _constant_omega_f1
,
103 static int _constant_omega_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
105 const double komega
= x
->data
[0];
106 const double kappa
= x
->data
[1];
108 HklPseudoAxisEngine
*engine
= params
;
109 double omega0
= engine
->mode
->parameters
[0].value
;
111 CHECK_NAN(x
->data
, x
->size
);
113 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) + M_PI_2
;
115 RUBh_minus_Q(x
->data
, params
, f
->data
);
116 f
->data
[3] = omega0
- omega
;
121 static const HklFunction constant_omega_f2
= {
122 .function
= _constant_omega_f2
,
126 static int _constant_chi_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
128 const double kappa
= x
->data
[1];
130 HklPseudoAxisEngine
*engine
= params
;
131 double chi0
= engine
->mode
->parameters
[0].value
;
133 CHECK_NAN(x
->data
, x
->size
);
135 chi
= 2 * asin(sin(kappa
/2.) * sin(50 * HKL_DEGTORAD
));
137 RUBh_minus_Q(x
->data
, params
, f
->data
);
138 f
->data
[3] = chi0
- chi
;
143 static const HklFunction constant_chi_f1
= {
144 .function
= _constant_chi_f1
,
148 static int _constant_chi_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
150 const double kappa
= x
->data
[1];
152 HklPseudoAxisEngine
*engine
= params
;
153 double chi0
= engine
->mode
->parameters
[0].value
;
155 CHECK_NAN(x
->data
, x
->size
);
157 chi
= -2 * asin(sin(kappa
/2.) * sin(50 * HKL_DEGTORAD
));
159 RUBh_minus_Q(x
->data
, params
, f
->data
);
160 f
->data
[3] = chi0
- chi
;
165 static const HklFunction constant_chi_f2
= {
166 .function
= _constant_chi_f2
,
170 static int _constant_phi_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
172 const double kappa
= x
->data
[1];
173 const double kphi
= x
->data
[2];
175 HklPseudoAxisEngine
*engine
= params
;
176 double phi0
= engine
->mode
->parameters
[0].value
;
178 CHECK_NAN(x
->data
, x
->size
);
180 phi
= kphi
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) + M_PI_2
;
182 RUBh_minus_Q(x
->data
, params
, f
->data
);
183 f
->data
[3] = phi0
- phi
;
188 static const HklFunction constant_phi_f1
= {
189 .function
= _constant_phi_f1
,
193 static int _constant_phi_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
195 const double kappa
= x
->data
[1];
196 const double kphi
= x
->data
[2];
198 HklPseudoAxisEngine
*engine
= params
;
199 double phi0
= engine
->mode
->parameters
[0].value
;
201 CHECK_NAN(x
->data
, x
->size
);
203 phi
= kphi
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) - M_PI_2
;
205 RUBh_minus_Q(x
->data
, params
, f
->data
);
206 f
->data
[3] = phi0
- phi
;
211 static const HklFunction constant_phi_f2
= {
212 .function
= _constant_phi_f2
,
220 static HklPseudoAxisEngineMode
*bissector(void)
222 static const char* axes
[] = {"komega", "kappa", "kphi", "tth"};
223 static const HklFunction
*functions
[] = {&bissector_f1
, &bissector_f2
};
224 static const HklPseudoAxisEngineModeAutoInfo info
= {
225 INFO_AUTO(__func__
, axes
, functions
),
228 return hkl_pseudo_axis_engine_mode_auto_new(&info
,
229 &hkl_mode_operations
);
232 static HklPseudoAxisEngineMode
*constant_omega(void)
234 static const char* axes
[] = {"komega", "kappa", "kphi", "tth"};
235 static const HklFunction
*functions
[] = {&constant_omega_f1
, &constant_omega_f2
};
236 static const HklParameter parameters
[] = {
237 {HKL_PARAMETER_DEFAULTS_ANGLE
, .name
= "omega"},
239 static const HklPseudoAxisEngineModeAutoInfo info
= {
240 INFO_AUTO_WITH_PARAMS(__func__
, axes
, functions
, parameters
),
243 return hkl_pseudo_axis_engine_mode_auto_new(&info
,
244 &hkl_mode_operations
);
247 static HklPseudoAxisEngineMode
*constant_chi(void)
249 static const char* axes
[] = {"komega", "kappa", "kphi", "tth"};
250 static const HklFunction
*functions
[] = {&constant_chi_f1
, &constant_chi_f2
};
251 static const HklParameter parameters
[] = {
252 {HKL_PARAMETER_DEFAULTS_ANGLE
, .name
= "chi"},
254 static const HklPseudoAxisEngineModeAutoInfo info
= {
255 INFO_AUTO_WITH_PARAMS(__func__
, axes
, functions
, parameters
),
258 return hkl_pseudo_axis_engine_mode_auto_new(&info
,
259 &hkl_mode_operations
);
262 static HklPseudoAxisEngineMode
*constant_phi(void)
264 static const char* axes
[] = {"komega", "kappa", "kphi", "tth"};
265 static const HklFunction
*functions
[] = {&constant_phi_f1
, &constant_phi_f2
};
266 static const HklParameter parameters
[] = {
267 {HKL_PARAMETER_DEFAULTS_ANGLE
, .name
= "phi"},
269 static const HklPseudoAxisEngineModeAutoInfo info
= {
270 INFO_AUTO_WITH_PARAMS(__func__
, axes
, functions
, parameters
),
273 return hkl_pseudo_axis_engine_mode_auto_new(&info
,
274 &hkl_mode_operations
);
277 static HklPseudoAxisEngineMode
*double_diffraction(void)
279 static const char* axes
[] = {"komega", "kappa", "kphi", "tth"};
280 static const HklFunction
*functions
[] = {&double_diffraction_func
};
281 static const HklParameter parameters
[] = {
282 {HKL_PARAMETER_DEFAULTS
, .name
= "h2", .range
= {.min
=-1, .max
=1}, .value
= 1,},
283 {HKL_PARAMETER_DEFAULTS
, .name
= "k2", .range
= {.min
=-1, .max
=1}, .value
= 1,},
284 {HKL_PARAMETER_DEFAULTS
, .name
= "l2", .range
= {.min
=-1, .max
=1}, .value
= 1,},
286 static const HklPseudoAxisEngineModeAutoInfo info
= {
287 INFO_AUTO_WITH_PARAMS(__func__
, axes
, functions
, parameters
),
290 return hkl_pseudo_axis_engine_mode_auto_new(&info
,
291 &hkl_mode_operations
);
294 static HklPseudoAxisEngineMode
*psi_constant(void)
296 static const char* axes
[] = {"komega", "kappa", "kphi", "tth"};
297 static const HklFunction
*functions
[] = {&psi_constant_vertical_func
};
298 static const HklParameter parameters
[] = {
299 {HKL_PARAMETER_DEFAULTS
, .name
= "h2", .range
= {.min
=-1, .max
=1}, .value
= 1,},
300 {HKL_PARAMETER_DEFAULTS
, .name
= "k2", .range
= {.min
=-1, .max
=1}, .value
= 0,},
301 {HKL_PARAMETER_DEFAULTS
, .name
= "l2", .range
= {.min
=-1, .max
=1}, .value
= 0,},
302 {HKL_PARAMETER_DEFAULTS_ANGLE
, .name
= "psi"},
304 static const HklPseudoAxisEngineModeAutoInfo info
= {
305 INFO_AUTO_WITH_PARAMS(__func__
, axes
, functions
, parameters
),
308 return hkl_pseudo_axis_engine_mode_auto_new(&info
,
309 &psi_constant_vertical_mode_operations
);
312 /**********************/
313 /* pseudo axis engine */
314 /**********************/
316 HklPseudoAxisEngine
*hkl_pseudo_axis_engine_k4cv_hkl_new(void)
318 HklPseudoAxisEngine
*self
;
319 HklPseudoAxisEngineMode
*default_mode
;
321 self
= hkl_pseudo_axis_engine_hkl_new();
323 default_mode
= bissector();
324 hkl_pseudo_axis_engine_add_mode(self
, default_mode
);
325 hkl_pseudo_axis_engine_select_mode(self
, default_mode
);
327 hkl_pseudo_axis_engine_add_mode(self
, constant_omega());
328 hkl_pseudo_axis_engine_add_mode(self
, constant_chi());
329 hkl_pseudo_axis_engine_add_mode(self
, constant_phi());
330 hkl_pseudo_axis_engine_add_mode(self
, double_diffraction());
331 hkl_pseudo_axis_engine_add_mode(self
, psi_constant());