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-2019, 2022 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_multiroots.h>
23 #include "hkl-factory-private.h" // for autodata_factories_, etc
24 #include "hkl-axis-private.h" // for HklAxis
25 #include "hkl-pseudoaxis-common-hkl-private.h" // for hkl_engine_hkl_new, etc
26 #include "hkl-pseudoaxis-common-q-private.h" // for hkl_engine_q2_new, etc
27 #include "hkl-pseudoaxis-common-tth-private.h" // for hkl_engine_tth2_new, etc
28 #include "hkl-pseudoaxis-common-readonly-private.h"
40 /*********************/
41 /* MED 2+2 HklEngine */
42 /*********************/
44 static int _reflectivity_func(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
46 const double mu
= x
->data
[0];
47 const double gamma
= x
->data
[2];
49 CHECK_NAN(x
->data
, x
->size
);
51 RUBh_minus_Q(x
->data
, params
, f
->data
);
52 f
->data
[3] = gamma
- 2 * mu
;
57 static const HklFunction reflectivity_func
= {
58 .function
= _reflectivity_func
,
62 static HklMode
* mu_fixed_2_2()
64 static const char* axes_r
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
};
65 static const char* axes_w
[] = {OMEGA
, GAMMA
, DELTA
};
66 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
67 static const HklModeAutoInfo info
= {
68 HKL_MODE_AUTO_INFO("mu_fixed", axes_r
, axes_w
, functions
),
71 return hkl_mode_auto_new(&info
,
72 &hkl_full_mode_operations
,
76 static HklMode
* reflectivity_2_2()
78 static const char* axes_r
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
};
79 static const char* axes_w
[] = {MU
, OMEGA
, GAMMA
, DELTA
};
80 static const HklFunction
*functions
[] = {&reflectivity_func
};
81 static const HklModeAutoInfo info
= {
82 HKL_MODE_AUTO_INFO("reflectivity", axes_r
, axes_w
, functions
),
85 return hkl_mode_auto_new(&info
,
86 &hkl_full_mode_operations
,
90 static HklMode
*emergence_fixed_2_2()
92 static const char* axes_r
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
};
93 static const char* axes_w
[] = {MU
, OMEGA
, GAMMA
, DELTA
};
94 static const HklFunction
* functions
[] = {&emergence_fixed_func
};
95 static const HklParameter parameters
[] = {
96 HKL_MODE_HKL_EMERGENCE_FIXED_PARAMETERS_DEFAULTS(0, 1, 0, 0),
98 static const HklModeAutoInfo info
= {
99 HKL_MODE_AUTO_INFO_WITH_PARAMS("emergence_fixed", axes_r
, axes_w
,
100 functions
, parameters
),
103 return hkl_mode_hkl_emergence_fixed_new(&info
);
106 static HklEngine
*hkl_engine_soleil_sixs_med_2_2_hkl_new(HklEngineList
*engines
)
109 HklMode
*default_mode
;
111 self
= hkl_engine_hkl_new(engines
);
113 default_mode
= mu_fixed_2_2();
114 hkl_engine_add_mode(self
, default_mode
);
115 hkl_engine_mode_set(self
, default_mode
);
117 hkl_engine_add_mode(self
, reflectivity_2_2());
118 hkl_engine_add_mode(self
, emergence_fixed_2_2());
125 REGISTER_READONLY_INCIDENCE(hkl_engine_soleil_sixs_med_2_2_incidence_new
,
126 P99_PROTECT({BETA
, MU
, OMEGA
}),
127 surface_parameters_y
);
129 REGISTER_READONLY_EMERGENCE(hkl_engine_soleil_sixs_med_2_2_emergence_new
,
130 P99_PROTECT({BETA
, MU
, OMEGA
, GAMMA
, DELTA
}),
131 surface_parameters_y
);
134 /*********************/
135 /* MED 1+2 HklEngine */
136 /*********************/
138 static HklMode
* pitch_fixed()
140 static const char *axes_r
[] = {PITCH
, MU
, GAMMA
, DELTA
};
141 static const char* axes_w
[] = {MU
, GAMMA
, DELTA
};
142 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
143 static const HklModeAutoInfo info
= {
144 HKL_MODE_AUTO_INFO(__func__
, axes_r
, axes_w
, functions
),
147 return hkl_mode_auto_new(&info
,
148 &hkl_full_mode_operations
,
152 static HklMode
*delta_fixed()
154 static const char *axes_r
[] = {PITCH
, MU
, GAMMA
, DELTA
};
155 static const char* axes_w
[] = {PITCH
, MU
, GAMMA
};
156 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
157 static const HklModeAutoInfo info
= {
158 HKL_MODE_AUTO_INFO(__func__
, axes_r
, axes_w
, functions
),
161 return hkl_mode_auto_new(&info
,
162 &hkl_full_mode_operations
,
166 static HklEngine
*hkl_engine_soleil_sixs_med_1_2_hkl_new(HklEngineList
*engines
)
169 HklMode
*default_mode
;
171 self
= hkl_engine_hkl_new(engines
);
173 default_mode
= pitch_fixed();
174 hkl_engine_add_mode(self
, default_mode
);
175 hkl_engine_mode_set(self
, default_mode
);
177 hkl_engine_add_mode(self
, delta_fixed());
184 REGISTER_READONLY_INCIDENCE(hkl_engine_soleil_sixs_med_1_2_incidence_new
,
185 P99_PROTECT({PITCH
, MU
}),
186 surface_parameters_z
);
188 REGISTER_READONLY_EMERGENCE(hkl_engine_soleil_sixs_med_1_2_emergence_new
,
189 P99_PROTECT({PITCH
, MU
, GAMMA
, DELTA
}),
190 surface_parameters_z
);
192 /*********************/
193 /* MED 2+3 HklEngine */
194 /*********************/
196 typedef struct _HklSlitsFit HklSlitsFit
;
199 HklGeometry
*geometry
;
201 unsigned int slits_id
;
206 static int slits_func(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
208 double const *x_data
= gsl_vector_const_ptr(x
, 0);
209 double *f_data
= gsl_vector_ptr(f
, 0);
210 HklVector n_slits
= {{0, 0, 1}};
211 HklSlitsFit
*parameters
= params
;
213 hkl_parameter_value_set(parameters
->axis
, x_data
[0], HKL_UNIT_DEFAULT
, NULL
);
214 hkl_geometry_update(parameters
->geometry
);
216 /* compute the orientation of the slits */
217 hkl_vector_rotated_quaternion(&n_slits
,
218 &darray_item(parameters
->geometry
->holders
, 1)->q
);
220 /* both directions must be perpendicular */
221 f_data
[0] = hkl_vector_scalar_product(¶meters
->surface
, &n_slits
);
226 static int fit_slits_orientation(HklSlitsFit
*params
)
229 gsl_multiroot_fsolver_type
const *T
;
230 gsl_multiroot_fsolver
*s
;
231 gsl_multiroot_function f
;
238 /* now solve the system */
239 /* Initialize method */
240 T
= gsl_multiroot_fsolver_hybrid
;
241 s
= gsl_multiroot_fsolver_alloc (T
, params
->len
);
242 x
= gsl_vector_alloc(params
->len
);
243 x_data
= gsl_vector_ptr(x
, 0);
245 /* initialize x with the right values */
246 x_data
[0] = params
->axis
->_value
;
251 gsl_multiroot_fsolver_set (s
, &f
, x
);
253 /* iterate to find the solution */
257 status
= gsl_multiroot_fsolver_iterate(s
);
258 if (status
|| iter
% 100 == 0) {
259 /* Restart from another point. */
260 for(i
=0; i
<params
->len
; ++i
)
261 x_data
[i
] = (double)rand() / RAND_MAX
* 180. / M_PI
;
262 gsl_multiroot_fsolver_set(s
, &f
, x
);
263 gsl_multiroot_fsolver_iterate(s
);
265 status
= gsl_multiroot_test_residual (s
->f
, HKL_EPSILON
);
266 } while (status
== GSL_CONTINUE
&& iter
< 1000);
269 fprintf(stdout
, "\n fitting the detector position using thoses axes :");
270 for(i
=0; i
<params
->len
; ++i
)
271 fprintf(stdout
, " \"%s\"", params
->axis
->name
);
272 fprintf(stdout
, " status : %d iter : %d", status
, iter
);
273 fprintf(stdout
, " x: [");
274 for(i
=0; i
<params
->len
; ++i
)
275 fprintf(stdout
, " %.7f", s
->x
->data
[i
]);
276 fprintf(stdout
, "] f: [");
277 for(i
=0; i
<params
->len
; ++i
)
278 fprintf(stdout
, " %.7f", s
->f
->data
[i
]);
279 fprintf(stdout
, "]\n");
280 hkl_geometry_fprintf(stdout
, params
->geometry
);
282 if(status
!= GSL_CONTINUE
){
284 /* put the axes in the -pi, pi range. */
285 gsl_sf_angle_restrict_pos_e(¶ms
->axis
->_value
);
289 gsl_multiroot_fsolver_free(s
);
294 static void hkl_geometry_list_multiply_soleil_sixs_med_2_3(HklGeometryList
*self
,
295 HklGeometryListItem
*item
) HKL_ARG_NONNULL(1, 2);
296 static void hkl_geometry_list_multiply_soleil_sixs_med_2_3(HklGeometryList
*self
,
297 HklGeometryListItem
*item
)
300 HklGeometry
*geometry
;
301 double slits_position
;
302 HklHolder
*sample_holder
;
303 HklHolder
*detector_holder
;
305 /* For each solution already found we will generate another one */
306 /* we will set the right slit orientation for a given detector arm position */
307 geometry
= item
->geometry
;
308 sample_holder
= darray_item(geometry
->holders
, 0);
309 detector_holder
= darray_item(geometry
->holders
, 1);
311 /* get the index of the axis corresponding to the slits */
312 /* for now the last holder is the detector one */
313 params
.slits_id
= detector_holder
->config
->idx
[detector_holder
->config
->len
-1];
314 params
.len
= 1; /* only one axis to fit */
315 params
.geometry
= geometry
;
316 params
.axis
= darray_item(params
.geometry
->axes
, params
.slits_id
);
318 /* compute the surface orientation fixed during the fit */
319 /* use the last sample axis as sample surface normal */
320 params
.surface
= container_of(darray_item(geometry
->axes
,
321 sample_holder
->config
->idx
[sample_holder
->config
->len
- 1]),
322 HklAxis
, parameter
)->axis_v
;
323 hkl_vector_rotated_quaternion(¶ms
.surface
,
327 /* we just need to fit the slits orientation */
328 /* save it's value before */
329 slits_position
= hkl_parameter_value_get(params
.axis
, HKL_UNIT_DEFAULT
);
330 if (fit_slits_orientation(¶ms
) != TRUE
)
331 hkl_parameter_value_set(params
.axis
, slits_position
, HKL_UNIT_DEFAULT
, NULL
);
334 static HklMode
* mu_fixed_2_3()
336 static const char *axes_r
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
337 static const char* axes_w
[] = {OMEGA
, GAMMA
, DELTA
};
338 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
339 static const HklModeAutoInfo info
= {
340 HKL_MODE_AUTO_INFO("mu_fixed", axes_r
, axes_w
, functions
),
343 return hkl_mode_auto_new(&info
,
344 &hkl_full_mode_operations
,
348 static HklMode
* gamma_fixed_2_3()
350 static const char *axes_r
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
351 static const char* axes_w
[] = {MU
, OMEGA
, DELTA
};
352 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
353 static const HklModeAutoInfo info
= {
354 HKL_MODE_AUTO_INFO("gamma_fixed", axes_r
, axes_w
, functions
),
357 return hkl_mode_auto_new(&info
,
358 &hkl_full_mode_operations
,
362 static HklMode
*emergence_fixed_2_3()
364 static const char* axes_r
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
365 static const char* axes_w
[] = {MU
, OMEGA
, GAMMA
, DELTA
};
366 static const HklFunction
* functions
[] = {&emergence_fixed_func
};
367 static const HklParameter parameters
[] = {
368 HKL_MODE_HKL_EMERGENCE_FIXED_PARAMETERS_DEFAULTS(0, 1, 0, 0),
370 static const HklModeAutoInfo info
= {
371 HKL_MODE_AUTO_INFO_WITH_PARAMS("emergence_fixed", axes_r
, axes_w
,
372 functions
, parameters
),
375 return hkl_mode_hkl_emergence_fixed_new(&info
);
378 static HklEngine
*hkl_engine_soleil_sixs_med_2_3_hkl_new(HklEngineList
*engines
)
381 HklMode
*default_mode
;
383 self
= hkl_engine_hkl_new(engines
);
385 default_mode
= mu_fixed_2_3();
386 hkl_engine_add_mode(self
, default_mode
);
387 hkl_engine_mode_set(self
, default_mode
);
389 hkl_engine_add_mode(self
, gamma_fixed_2_3());
390 hkl_engine_add_mode(self
, emergence_fixed_2_3());
395 /***********************/
396 /* SOLEIL SIXS MED 2+2 */
397 /***********************/
399 #define HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_2_2_DESCRIPTION \
400 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
401 "+ 3 axes for the sample\n" \
403 " + **" BETA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
404 " + **" MU "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
405 " + **" OMEGA "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
407 "+ 3 axis for the detector\n" \
409 " + **" BETA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
410 " + **" GAMMA "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
411 " + **" DELTA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n"
413 static const char* hkl_geometry_soleil_sixs_med_2_2_axes
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
};
415 static HklGeometry
*hkl_geometry_new_soleil_sixs_med_2_2(const HklFactory
*factory
)
417 HklGeometry
*self
= hkl_geometry_new(factory
, &hkl_geometry_operations_defaults
);
420 h
= hkl_geometry_add_holder(self
);
421 hkl_holder_add_rotation(h
, BETA
, 0, -1, 0, &hkl_unit_angle_deg
);
422 hkl_holder_add_rotation(h
, MU
, 0, 0, 1, &hkl_unit_angle_deg
);
423 hkl_holder_add_rotation(h
, OMEGA
, 0, -1, 0, &hkl_unit_angle_deg
);
425 h
= hkl_geometry_add_holder(self
);
426 hkl_holder_add_rotation(h
, BETA
, 0, -1, 0, &hkl_unit_angle_deg
);
427 hkl_holder_add_rotation(h
, GAMMA
, 0, 0, 1, &hkl_unit_angle_deg
);
428 hkl_holder_add_rotation(h
, DELTA
, 0, -1, 0, &hkl_unit_angle_deg
);
433 static HklEngineList
*hkl_engine_list_new_soleil_sixs_med_2_2(const HklFactory
*factory
)
435 HklEngineList
*self
= hkl_engine_list_new();
437 hkl_engine_soleil_sixs_med_2_2_hkl_new(self
);
438 hkl_engine_q2_new(self
);
439 hkl_engine_qper_qpar_new(self
);
440 hkl_engine_tth2_new(self
);
441 hkl_engine_soleil_sixs_med_2_2_incidence_new(self
);
442 hkl_engine_soleil_sixs_med_2_2_emergence_new(self
);
447 REGISTER_DIFFRACTOMETER(soleil_sixs_med_2_2
,"SOLEIL SIXS MED2+2", HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_2_2_DESCRIPTION
);
449 /***********************/
450 /* SOLEIL SIXS MED 1+2 */
451 /***********************/
453 #define HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_1_2_DESCRIPTION \
454 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
455 "+ 2 axes for the sample\n" \
457 " + **" PITCH "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
458 " + **" MU "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
460 "+ 3 axis for the detector\n" \
462 " + **" PITCH "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
463 " + **" GAMMA "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
464 " + **" DELTA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n"
466 static const char* hkl_geometry_soleil_sixs_med_1_2_axes
[] = {PITCH
, MU
, GAMMA
, DELTA
};
468 static HklGeometry
*hkl_geometry_new_soleil_sixs_med_1_2(const HklFactory
*factory
)
470 HklGeometry
*self
= hkl_geometry_new(factory
, &hkl_geometry_operations_defaults
);
472 h
= hkl_geometry_add_holder(self
);
473 hkl_holder_add_rotation(h
, PITCH
, 0, -1, 0, &hkl_unit_angle_deg
);
474 hkl_holder_add_rotation(h
, MU
, 0, 0, 1, &hkl_unit_angle_deg
);
476 h
= hkl_geometry_add_holder(self
);
477 hkl_holder_add_rotation(h
, PITCH
, 0, -1, 0, &hkl_unit_angle_deg
);
478 hkl_holder_add_rotation(h
, GAMMA
, 0, 0, 1, &hkl_unit_angle_deg
);
479 hkl_holder_add_rotation(h
, DELTA
, 0, -1, 0, &hkl_unit_angle_deg
);
484 static HklEngineList
*hkl_engine_list_new_soleil_sixs_med_1_2(const HklFactory
*factory
)
486 HklEngineList
*self
= hkl_engine_list_new();
488 hkl_engine_soleil_sixs_med_1_2_hkl_new(self
);
489 hkl_engine_q2_new(self
);
490 hkl_engine_qper_qpar_new(self
);
491 hkl_engine_tth2_new(self
);
492 hkl_engine_soleil_sixs_med_1_2_incidence_new(self
);
493 hkl_engine_soleil_sixs_med_1_2_emergence_new(self
);
498 REGISTER_DIFFRACTOMETER(soleil_sixs_med_1_2
, "SOLEIL SIXS MED1+2", HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_1_2_DESCRIPTION
);
501 /******************************/
502 /* SOLEIL SIXS MED 2+3 (MedV) */
503 /******************************/
505 #define HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_2_3_DESCRIPTION \
506 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
507 "+ 3 axes for the sample\n" \
509 " + **" BETA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
510 " + **" MU "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
511 " + **" OMEGA "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
513 "+ 4 axis for the detector\n" \
515 " + **" BETA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
516 " + **" GAMMA "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
517 " + **" DELTA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
518 " + **" ETA_A "** : rotation around the :math:`-\\vec{x}` direction (-1, 0, 0)\n"
520 static const char* hkl_geometry_soleil_sixs_med_2_3_axes
[] = {BETA
, MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
522 static HklGeometry
*hkl_geometry_new_soleil_sixs_med_2_3(const HklFactory
*factory
)
524 HklGeometry
*self
= hkl_geometry_new(factory
, &hkl_geometry_operations_defaults
);
527 h
= hkl_geometry_add_holder(self
);
528 hkl_holder_add_rotation(h
, BETA
, 0, -1, 0, &hkl_unit_angle_deg
);
529 hkl_holder_add_rotation(h
, MU
, 0, 0, 1, &hkl_unit_angle_deg
);
530 hkl_holder_add_rotation(h
, OMEGA
, 0, -1, 0, &hkl_unit_angle_deg
);
532 h
= hkl_geometry_add_holder(self
);
533 hkl_holder_add_rotation(h
, BETA
, 0, -1, 0, &hkl_unit_angle_deg
);
534 hkl_holder_add_rotation(h
, GAMMA
, 0, 0, 1, &hkl_unit_angle_deg
);
535 hkl_holder_add_rotation(h
, DELTA
, 0, -1, 0, &hkl_unit_angle_deg
);
536 hkl_holder_add_rotation(h
, ETA_A
, -1, 0, 0, &hkl_unit_angle_deg
);
541 static HklEngineList
*hkl_engine_list_new_soleil_sixs_med_2_3(const HklFactory
*factory
)
543 HklEngineList
*self
= hkl_engine_list_new();
545 self
->geometries
->multiply
= hkl_geometry_list_multiply_soleil_sixs_med_2_3
;
546 hkl_engine_soleil_sixs_med_2_3_hkl_new(self
);
547 hkl_engine_q2_new(self
);
548 hkl_engine_qper_qpar_new(self
);
549 hkl_engine_tth2_new(self
);
550 hkl_engine_soleil_sixs_med_2_2_incidence_new(self
);
551 hkl_engine_soleil_sixs_med_2_2_emergence_new(self
);
556 REGISTER_DIFFRACTOMETER(soleil_sixs_med_2_3
, "SOLEIL SIXS MED2+3", HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_2_3_DESCRIPTION
);
559 /**************************/
560 /* SOLEIL SIXS MED 2+3 v2 */
561 /**************************/
563 static HklMode
* mu_fixed_2_3_v2()
565 static const char *axes_r
[] = {MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
566 static const char* axes_w
[] = {OMEGA
, GAMMA
, DELTA
};
567 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
568 static const HklModeAutoInfo info
= {
569 HKL_MODE_AUTO_INFO("mu_fixed", axes_r
, axes_w
, functions
),
572 return hkl_mode_auto_new(&info
,
573 &hkl_full_mode_operations
,
577 static HklMode
* gamma_fixed_2_3_v2()
579 static const char *axes_r
[] = {MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
580 static const char* axes_w
[] = {MU
, OMEGA
, DELTA
};
581 static const HklFunction
*functions
[] = {&RUBh_minus_Q_func
};
582 static const HklModeAutoInfo info
= {
583 HKL_MODE_AUTO_INFO("gamma_fixed", axes_r
, axes_w
, functions
),
586 return hkl_mode_auto_new(&info
,
587 &hkl_full_mode_operations
,
591 static HklMode
*emergence_fixed_2_3_v2()
593 static const char* axes_r
[] = {MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
594 static const char* axes_w
[] = {MU
, OMEGA
, GAMMA
, DELTA
};
595 static const HklFunction
* functions
[] = {&emergence_fixed_func
};
596 static const HklParameter parameters
[] = {
597 HKL_MODE_HKL_EMERGENCE_FIXED_PARAMETERS_DEFAULTS(0, 1, 0, 0),
599 static const HklModeAutoInfo info
= {
600 HKL_MODE_AUTO_INFO_WITH_PARAMS("emergence_fixed", axes_r
, axes_w
,
601 functions
, parameters
),
604 return hkl_mode_hkl_emergence_fixed_new(&info
);
608 static HklEngine
*hkl_engine_soleil_sixs_med_2_3_v2_hkl_new(HklEngineList
*engines
)
611 HklMode
*default_mode
;
613 self
= hkl_engine_hkl_new(engines
);
615 default_mode
= mu_fixed_2_3_v2();
616 hkl_engine_add_mode(self
, default_mode
);
617 hkl_engine_mode_set(self
, default_mode
);
619 hkl_engine_add_mode(self
, gamma_fixed_2_3_v2());
620 hkl_engine_add_mode(self
, emergence_fixed_2_3_v2());
626 #define HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_2_3_V2_DESCRIPTION \
627 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
628 "+ 2 axes for the sample\n" \
630 " + **" MU "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
631 " + **" OMEGA "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
633 "+ 3 axis for the detector\n" \
635 " + **" GAMMA "** : rotation around the :math:`\\vec{z}` direction (0, 0, 1)\n" \
636 " + **" DELTA "** : rotation around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
637 " + **" ETA_A "** : rotation around the :math:`-\\vec{x}` direction (-1, 0, 0)\n"
639 static const char* hkl_geometry_soleil_sixs_med_2_3_v2_axes
[] = {MU
, OMEGA
, GAMMA
, DELTA
, ETA_A
};
641 static HklGeometry
*hkl_geometry_new_soleil_sixs_med_2_3_v2(const HklFactory
*factory
)
643 HklGeometry
*self
= hkl_geometry_new(factory
, &hkl_geometry_operations_defaults
);
646 h
= hkl_geometry_add_holder(self
);
647 hkl_holder_add_rotation(h
, MU
, 0, 0, 1, &hkl_unit_angle_deg
);
648 hkl_holder_add_rotation(h
, OMEGA
, 0, -1, 0, &hkl_unit_angle_deg
);
650 h
= hkl_geometry_add_holder(self
);
651 hkl_holder_add_rotation(h
, GAMMA
, 0, 0, 1, &hkl_unit_angle_deg
);
652 hkl_holder_add_rotation(h
, DELTA
, 0, -1, 0, &hkl_unit_angle_deg
);
653 hkl_holder_add_rotation(h
, ETA_A
, -1, 0, 0, &hkl_unit_angle_deg
);
658 static inline int hkl_engine_list_post_engine_set_med_2_3_v2_real(HklEngineList
*self
)
661 int eta_a_rotation
= darray_item(self
->parameters
, 0)->_value
;
663 if(!self
|| !self
->geometries
)
666 if(eta_a_rotation
== 1){
668 uint len
= self
->geometries
->n_items
;
669 HklGeometryListItem
*item
;
672 * warning this method change the self->len so we need to save it
673 * before using the recursive perm_r calls
675 for(i
=0, item
=list_top(&self
->geometries
->items
, HklGeometryListItem
, list
);
676 i
<len
&& NULL
!= item
;
677 ++i
, item
=list_next(&self
->geometries
->items
, item
, list
))
678 hkl_geometry_list_multiply_soleil_sixs_med_2_3(self
->geometries
, item
);
684 static HklEngineList
*hkl_engine_list_new_soleil_sixs_med_2_3_v2(const HklFactory
*factory
)
686 static const HklParameter eta_a_rotation
= {
687 HKL_PARAMETER_DEFAULTS
, .name
= "eta_a_rotation",
689 .description
= "rotation of the detector (zaxis-like)",
690 .range
= { .min
=0, .max
=1 },
692 static const HklParameter
*parameters
[] = { &eta_a_rotation
};
693 static const HklEngineListInfo info
= {HKL_ENGINE_LIST_INFO(parameters
)};
694 static const HklEngineListOperations ops
= {
695 HKL_ENGINE_LIST_OPERATIONS_DEFAULTS
,
696 .post_engine_set
=hkl_engine_list_post_engine_set_med_2_3_v2_real
,
698 HklEngineList
*self
= hkl_engine_list_new_with_info(&info
, &ops
);
700 hkl_engine_soleil_sixs_med_2_3_v2_hkl_new(self
);
701 hkl_engine_q2_new(self
);
702 hkl_engine_qper_qpar_new(self
);
703 hkl_engine_tth2_new(self
);
704 hkl_engine_soleil_sixs_med_2_2_incidence_new(self
);
705 hkl_engine_soleil_sixs_med_2_2_emergence_new(self
);
710 REGISTER_DIFFRACTOMETER(soleil_sixs_med_2_3_v2
, "SOLEIL SIXS MED2+3 v2", HKL_GEOMETRY_TYPE_SOLEIL_SIXS_MED_2_3_V2_DESCRIPTION
);