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-2017 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
28 #include "hkl-pseudoaxis-common-readonly-private.h"
30 #define KOMEGA "komega"
35 static void hkl_geometry_list_multiply_k4c_real(HklGeometryList
*self
,
36 HklGeometryListItem
*item
)
38 HklGeometry
*geometry
;
40 double komega
, komegap
;
44 geometry
= item
->geometry
;
45 komega
= hkl_parameter_value_get(darray_item(geometry
->axes
, 0), HKL_UNIT_DEFAULT
);
46 kappa
= hkl_parameter_value_get(darray_item(geometry
->axes
, 1), HKL_UNIT_DEFAULT
);
47 kphi
= hkl_parameter_value_get(darray_item(geometry
->axes
, 2), HKL_UNIT_DEFAULT
);
49 kappa_2_kappap(komega
, kappa
, kphi
, 50 * HKL_DEGTORAD
, &komegap
, &kappap
, &kphip
);
51 copy
= hkl_geometry_new_copy(geometry
);
52 /* TODO parameter list for the geometry */
53 hkl_parameter_value_set(darray_item(copy
->axes
, 0), komegap
, HKL_UNIT_DEFAULT
, NULL
);
54 hkl_parameter_value_set(darray_item(copy
->axes
, 1), kappap
, HKL_UNIT_DEFAULT
, NULL
);
55 hkl_parameter_value_set(darray_item(copy
->axes
, 2), kphip
, HKL_UNIT_DEFAULT
, NULL
);
57 hkl_geometry_update(copy
);
58 hkl_geometry_list_add(self
, copy
);
59 hkl_geometry_free(copy
);
68 static int _bissector_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
70 const double komega
= x
->data
[0];
71 const double kappa
= x
->data
[1];
72 const double tth
= x
->data
[3];
75 CHECK_NAN(x
->data
, x
->size
);
77 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) + M_PI_2
;
79 RUBh_minus_Q(x
->data
, params
, f
->data
);
80 f
->data
[3] = fmod(tth
- 2 * fmod(omega
, M_PI
), 2*M_PI
);
85 static const HklFunction bissector_f1
= {
86 .function
= _bissector_f1
,
90 static int _bissector_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
92 const double komega
= x
->data
[0];
93 const double kappa
= x
->data
[1];
94 const double tth
= x
->data
[3];
97 CHECK_NAN(x
->data
, x
->size
);
99 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) - M_PI_2
;
101 RUBh_minus_Q(x
->data
, params
, f
->data
);
102 f
->data
[3] = fmod(tth
- 2 * fmod(omega
, M_PI
), 2*M_PI
);
107 static const HklFunction bissector_f2
= {
108 .function
= _bissector_f2
,
112 static HklMode
*bissector(void)
114 static const char* axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
115 static const HklFunction
*functions
[] = {&bissector_f1
, &bissector_f2
};
116 static const HklModeAutoInfo info
= {
117 HKL_MODE_AUTO_INFO(__func__
, axes
, axes
, functions
),
120 return hkl_mode_auto_new(&info
,
121 &hkl_mode_operations
,
127 static int _constant_omega_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
129 double const komega
= x
->data
[0];
130 double const kappa
= x
->data
[1];
132 HklEngine
*engine
= params
;
133 double omega0
= darray_item(engine
->mode
->parameters
, 0)->_value
;
135 CHECK_NAN(x
->data
, x
->size
);
137 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) - M_PI_2
;
139 RUBh_minus_Q(x
->data
, params
, f
->data
);
140 f
->data
[3] = omega0
- omega
;
145 static const HklFunction constant_omega_f1
= {
146 .function
= _constant_omega_f1
,
150 static int _constant_omega_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
152 const double komega
= x
->data
[0];
153 const double kappa
= x
->data
[1];
155 HklEngine
*engine
= params
;
156 double omega0
= darray_item(engine
->mode
->parameters
, 0)->_value
;
158 CHECK_NAN(x
->data
, x
->size
);
160 omega
= komega
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) + M_PI_2
;
162 RUBh_minus_Q(x
->data
, params
, f
->data
);
163 f
->data
[3] = omega0
- omega
;
168 static const HklFunction constant_omega_f2
= {
169 .function
= _constant_omega_f2
,
173 static HklMode
*constant_omega(void)
175 static const char* axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
176 static const HklFunction
*functions
[] = {&constant_omega_f1
, &constant_omega_f2
};
177 static const HklModeAutoInfo info
= {
178 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__
, axes
, axes
,
179 functions
, constant_omega_parameters
),
182 return hkl_mode_auto_new(&info
,
183 &hkl_mode_operations
,
189 static int _constant_chi_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
191 const double kappa
= x
->data
[1];
193 HklEngine
*engine
= params
;
194 double chi0
= darray_item(engine
->mode
->parameters
, 0)->_value
;
196 CHECK_NAN(x
->data
, x
->size
);
198 chi
= 2 * asin(sin(kappa
/2.) * sin(50 * HKL_DEGTORAD
));
200 RUBh_minus_Q(x
->data
, params
, f
->data
);
201 f
->data
[3] = chi0
- chi
;
206 static const HklFunction constant_chi_f1
= {
207 .function
= _constant_chi_f1
,
211 static int _constant_chi_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
213 const double kappa
= x
->data
[1];
215 HklEngine
*engine
= params
;
216 double chi0
= darray_item(engine
->mode
->parameters
, 0)->_value
;
218 CHECK_NAN(x
->data
, x
->size
);
220 chi
= -2 * asin(sin(kappa
/2.) * sin(50 * HKL_DEGTORAD
));
222 RUBh_minus_Q(x
->data
, params
, f
->data
);
223 f
->data
[3] = chi0
- chi
;
228 static const HklFunction constant_chi_f2
= {
229 .function
= _constant_chi_f2
,
233 static HklMode
*constant_chi(void)
235 static const char* axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
236 static const HklFunction
*functions
[] = {&constant_chi_f1
, &constant_chi_f2
};
237 static const HklModeAutoInfo info
= {
238 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__
, axes
, axes
,
239 functions
, constant_chi_parameters
),
242 return hkl_mode_auto_new(&info
,
243 &hkl_mode_operations
,
249 static int _constant_phi_f1(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
251 const double kappa
= x
->data
[1];
252 const double kphi
= x
->data
[2];
254 HklEngine
*engine
= params
;
255 double phi0
= darray_item(engine
->mode
->parameters
, 0)->_value
;
257 CHECK_NAN(x
->data
, x
->size
);
259 phi
= kphi
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) + M_PI_2
;
261 RUBh_minus_Q(x
->data
, params
, f
->data
);
262 f
->data
[3] = phi0
- phi
;
267 static const HklFunction constant_phi_f1
= {
268 .function
= _constant_phi_f1
,
272 static int _constant_phi_f2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
274 const double kappa
= x
->data
[1];
275 const double kphi
= x
->data
[2];
277 HklEngine
*engine
= params
;
278 double phi0
= darray_item(engine
->mode
->parameters
, 0)->_value
;
280 CHECK_NAN(x
->data
, x
->size
);
282 phi
= kphi
+ atan(tan(kappa
/2.)*cos(50 * HKL_DEGTORAD
)) - M_PI_2
;
284 RUBh_minus_Q(x
->data
, params
, f
->data
);
285 f
->data
[3] = phi0
- phi
;
290 static const HklFunction constant_phi_f2
= {
291 .function
= _constant_phi_f2
,
295 static HklMode
*constant_phi(void)
297 static const char* axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
298 static const HklFunction
*functions
[] = {&constant_phi_f1
, &constant_phi_f2
};
299 static const HklModeAutoInfo info
= {
300 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__
, axes
, axes
,
301 functions
, constant_phi_parameters
),
304 return hkl_mode_auto_new(&info
,
305 &hkl_mode_operations
,
309 static HklMode
*double_diffraction(void)
311 static const char* axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
312 static const HklFunction
*functions
[] = {&double_diffraction_func
};
313 static const HklModeAutoInfo info
= {
314 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__
, axes
, axes
,
315 functions
, double_diffraction_parameters
),
318 return hkl_mode_auto_new(&info
,
319 &hkl_mode_operations
,
323 static HklMode
*psi_constant(void)
325 static const char* axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
326 static const HklFunction
*functions
[] = {&psi_constant_vertical_func
};
327 static const HklModeAutoInfo info
= {
328 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__
, axes
, axes
,
329 functions
, psi_constant_parameters
),
332 return hkl_mode_auto_new(&info
,
333 &psi_constant_vertical_mode_operations
,
337 static HklEngine
*hkl_engine_k4cv_hkl_new(HklEngineList
*engines
)
340 HklMode
*default_mode
;
342 self
= hkl_engine_hkl_new(engines
);
344 default_mode
= bissector();
345 hkl_engine_add_mode(self
, default_mode
);
346 hkl_engine_mode_set(self
, default_mode
);
348 hkl_engine_add_mode(self
, constant_omega());
349 hkl_engine_add_mode(self
, constant_chi());
350 hkl_engine_add_mode(self
, constant_phi());
351 hkl_engine_add_mode(self
, double_diffraction());
352 hkl_engine_add_mode(self
, psi_constant());
362 static HklMode
*psi()
364 static const char *axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
365 static const HklFunction
*functions
[] = {&psi_func
};
366 static const HklModeAutoInfo info
= {
367 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__
, axes
, axes
,
368 functions
, psi_parameters
),
371 return hkl_mode_psi_new(&info
);
374 static HklEngine
*hkl_engine_k4cv_psi_new(HklEngineList
*engines
)
377 HklMode
*default_mode
;
379 self
= hkl_engine_psi_new(engines
);
381 default_mode
= psi();
382 hkl_engine_add_mode(self
, default_mode
);
383 hkl_engine_mode_set(self
, default_mode
);
392 REGISTER_READONLY_INCIDENCE(hkl_engine_kappa4C_vertical_incidence_new
,
393 P99_PROTECT({KOMEGA
, KAPPA
, KPHI
}),
394 surface_parameters_y
);
396 REGISTER_READONLY_EMERGENCE(hkl_engine_kappa4C_vertical_emergence_new
,
397 P99_PROTECT({KOMEGA
, KAPPA
, KPHI
, TTH
}),
398 surface_parameters_y
);
404 #define HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION \
405 "For this geometry there is a special parameters called :math:`\\alpha` which is the\n" \
406 "angle between the kappa rotation axis and the :math:`\\vec{y}` direction.\n" \
408 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
409 "+ 3 axes for the sample\n" \
411 " + **" KOMEGA "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
412 " + **" KAPPA "** : rotating around the :math:`\\vec{x}` direction (0, :math:`-\\cos\\alpha`, :math:`-\\sin\\alpha`)\n" \
413 " + **" KPHI "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
415 "+ 1 axis for the detector\n" \
417 " + **" TTH "** : rotation around the :math:`-\\\vec{y}` direction (0, -1, 0)\n"
419 static const char* hkl_geometry_kappa4C_vertical_axes
[] = {KOMEGA
, KAPPA
, KPHI
, TTH
};
421 static HklGeometry
*hkl_geometry_new_kappa4C_vertical(const HklFactory
*factory
)
423 HklGeometry
*self
= hkl_geometry_new(factory
, &hkl_geometry_operations_defaults
);
424 double alpha
= 50 * HKL_DEGTORAD
;
427 h
= hkl_geometry_add_holder(self
);
428 hkl_holder_add_rotation(h
, KOMEGA
, 0, -1, 0, &hkl_unit_angle_deg
);
429 hkl_holder_add_rotation(h
, KAPPA
, 0, -cos(alpha
), -sin(alpha
), &hkl_unit_angle_deg
);
430 hkl_holder_add_rotation(h
, KPHI
, 0, -1, 0, &hkl_unit_angle_deg
);
432 h
= hkl_geometry_add_holder(self
);
433 hkl_holder_add_rotation(h
, TTH
, 0, -1, 0, &hkl_unit_angle_deg
);
438 static HklEngineList
*hkl_engine_list_new_kappa4C_vertical(const HklFactory
*factory
)
440 HklEngineList
*self
= hkl_engine_list_new();
442 self
->geometries
->multiply
= hkl_geometry_list_multiply_k4c_real
;
443 hkl_engine_k4cv_hkl_new(self
);
444 hkl_engine_eulerians_new(self
);
445 hkl_engine_k4cv_psi_new(self
);
446 hkl_engine_q_new(self
);
447 hkl_engine_kappa4C_vertical_incidence_new(self
);
448 hkl_engine_kappa4C_vertical_emergence_new(self
);
453 REGISTER_DIFFRACTOMETER(kappa4C_vertical
, "K4CV", HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION
);