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
;
34 double komega
, komegap
;
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
);
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];
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
);
79 static const HklFunction bissector_f1
= {
80 .function
= _bissector_f1
,
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];
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
);
101 static const HklFunction bissector_f2
= {
102 .function
= _bissector_f2
,
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
,
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];
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
;
139 static const HklFunction constant_omega_f1
= {
140 .function
= _constant_omega_f1
,
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];
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
;
162 static const HklFunction constant_omega_f2
= {
163 .function
= _constant_omega_f2
,
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
,
183 static int _constant_chi_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
185 const double kappa
= x
->data
[1];
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
;
200 static const HklFunction constant_chi_f1
= {
201 .function
= _constant_chi_f1
,
205 static int _constant_chi_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
207 const double kappa
= x
->data
[1];
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
;
222 static const HklFunction constant_chi_f2
= {
223 .function
= _constant_chi_f2
,
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
,
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];
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
;
261 static const HklFunction constant_phi_f1
= {
262 .function
= _constant_phi_f1
,
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];
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
;
284 static const HklFunction constant_phi_f2
= {
285 .function
= _constant_phi_f2
,
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
,
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
,
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
,
331 static HklEngine
*hkl_engine_k4cv_hkl_new(void)
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());
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)
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
);
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" \
390 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
391 "+ 3 axes for the sample\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" \
397 "+ 1 axis for the detector\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
;
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);
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());
433 REGISTER_DIFFRACTOMETER(kappa4C_vertical
, "K4CV", HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION
);