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-2010 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>
24 #include <gsl/gsl_sf_trig.h>
25 #include <hkl/hkl-pseudoaxis.h>
26 #include <hkl/hkl-pseudoaxis-common.h>
27 #include <hkl/hkl-pseudoaxis-common-hkl.h>
28 #include <hkl/hkl-pseudoaxis-auto.h>
29 /***************************************/
30 /* common methode use by getter/setter */
31 /***************************************/
33 int RUBh_minus_Q_func(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
35 double const *x_data
= gsl_vector_const_ptr(x
, 0);
36 double *f_data
= gsl_vector_ptr(f
, 0);
38 RUBh_minus_Q(x_data
, params
, f_data
);
43 int RUBh_minus_Q(double const x
[], void *params
, double f
[])
47 HklPseudoAxisEngine
*engine
;
53 // update the workspace from x;
54 for(i
=0; i
<HKL_LIST_LEN(engine
->axes
); ++i
)
55 hkl_axis_set_value(engine
->axes
[i
], x
[i
]);
56 hkl_geometry_update(engine
->geometry
);
59 ((HklParameter
*)engine
->pseudoAxes
[0])->value
,
60 ((HklParameter
*)engine
->pseudoAxes
[1])->value
,
61 ((HklParameter
*)engine
->pseudoAxes
[2])->value
);
64 // for now the 0 holder is the sample holder.
65 holder
= &engine
->geometry
->holders
[0];
66 hkl_matrix_times_vector(&engine
->sample
->UB
, &Hkl
);
67 hkl_vector_rotated_quaternion(&Hkl
, &holder
->q
);
70 hkl_source_compute_ki(&engine
->geometry
->source
, &ki
);
71 hkl_detector_compute_kf(engine
->detector
, engine
->geometry
, &dQ
);
72 hkl_vector_minus_vector(&dQ
, &ki
);
74 hkl_vector_minus_vector(&dQ
, &Hkl
);
83 int hkl_pseudo_axis_engine_mode_get_hkl_real(HklPseudoAxisEngineMode
*self
,
84 HklPseudoAxisEngine
*engine
,
85 HklGeometry
*geometry
,
86 HklDetector
*detector
,
96 // update the geometry internals
97 hkl_geometry_update(geometry
);
100 // for now the 0 holder is the sample holder.
101 holder
= &geometry
->holders
[0];
102 hkl_quaternion_to_matrix(&holder
->q
, &RUB
);
103 hkl_matrix_times_matrix(&RUB
, &sample
->UB
);
106 hkl_source_compute_ki(&geometry
->source
, &ki
);
107 hkl_detector_compute_kf(detector
, geometry
, &Q
);
108 hkl_vector_minus_vector(&Q
, &ki
);
110 hkl_matrix_solve(&RUB
, &hkl
, &Q
);
112 // compute the min and max
116 // update the pseudoAxes config part
117 for(i
=0;i
<HKL_LIST_LEN(engine
->pseudoAxes
);++i
){
118 HklParameter
*parameter
= (HklParameter
*)(engine
->pseudoAxes
[i
]);
119 parameter
->value
= hkl
.data
[i
];
120 parameter
->range
.min
= min
;
121 parameter
->range
.max
= max
;
127 /***************************************/
128 /* the double diffraction get set part */
129 /***************************************/
131 int double_diffraction_func(gsl_vector
const *x
, void *params
, gsl_vector
*f
)
133 double const *x_data
= gsl_vector_const_ptr(x
, 0);
134 double *f_data
= gsl_vector_ptr(f
, 0);
136 double_diffraction(x_data
, params
, f_data
);
141 int double_diffraction(double const x
[], void *params
, double f
[])
143 HklPseudoAxisEngine
*engine
= params
;
150 // update the workspace from x;
151 for(i
=0; i
<HKL_LIST_LEN(engine
->axes
); ++i
)
152 hkl_axis_set_value(engine
->axes
[i
], x
[i
]);
153 hkl_geometry_update(engine
->geometry
);
155 hkl_vector_init(&hkl
,
156 ((HklParameter
*)engine
->pseudoAxes
[0])->value
,
157 ((HklParameter
*)engine
->pseudoAxes
[1])->value
,
158 ((HklParameter
*)engine
->pseudoAxes
[2])->value
);
160 hkl_vector_init(&kf2
,
161 engine
->mode
->parameters
[0].value
,
162 engine
->mode
->parameters
[1].value
,
163 engine
->mode
->parameters
[2].value
);
166 // for now the 0 holder is the sample holder.
167 holder
= &engine
->geometry
->holders
[0];
168 hkl_matrix_times_vector(&engine
->sample
->UB
, &hkl
);
169 hkl_vector_rotated_quaternion(&hkl
, &holder
->q
);
172 hkl_source_compute_ki(&engine
->geometry
->source
, &ki
);
173 hkl_detector_compute_kf(engine
->detector
, engine
->geometry
, &dQ
);
174 hkl_vector_minus_vector(&dQ
, &ki
);
175 hkl_vector_minus_vector(&dQ
, &hkl
);
177 // R * UB * hlk2 = Q2
178 hkl_matrix_times_vector(&engine
->sample
->UB
, &kf2
);
179 hkl_vector_rotated_quaternion(&kf2
, &holder
->q
);
180 hkl_vector_add_vector(&kf2
, &ki
);
185 f
[3] = hkl_vector_norm2(&kf2
) - hkl_vector_norm2(&ki
);
190 /******************************************/
191 /* the psi_constant_vertical get set part */
192 /******************************************/
194 int psi_constant_vertical_func(gsl_vector
const *x
, void *params
, gsl_vector
*f
)
197 double const *x_data
= gsl_vector_const_ptr(x
, 0);
198 double *f_data
= gsl_vector_ptr(f
, 0);
201 HklVector ki
, kf
, Q
, n
;
202 HklPseudoAxisEngine
*engine
;
205 RUBh_minus_Q(x_data
, params
, f_data
);
208 // update the workspace from x;
209 for(i
=0; i
<HKL_LIST_LEN(engine
->axes
); ++i
)
210 hkl_axis_set_value(engine
->axes
[i
], x_data
[i
]);
211 hkl_geometry_update(engine
->geometry
);
213 hkl_vector_init(&hkl
, 1, 0, 0);
216 hkl_source_compute_ki(&engine
->geometry
->source
, &ki
);
217 hkl_detector_compute_kf(engine
->detector
, engine
->geometry
, &kf
);
219 hkl_vector_minus_vector(&Q
, &ki
);
221 hkl_vector_normalize(&Q
);
223 hkl_vector_vectorial_product(&n
, &ki
);
224 hkl_vector_vectorial_product(&n
, &Q
);
227 hkl_vector_times_smatrix(&hkl
, &engine
->sample
->UB
);
228 hkl_vector_rotated_quaternion(&hkl
, &engine
->geometry
->holders
[0].q
);
230 // project hkl on the plan of normal Q
231 hkl_vector_project_on_plan(&hkl
, &Q
);
233 f_data
[3] = engine
->mode
->parameters
[3].value
- hkl_vector_oriented_angle(&n
, &hkl
, &Q
);
238 int hkl_pseudo_axis_engine_mode_init_psi_constant_vertical_real(HklPseudoAxisEngineMode
*self
,
239 HklPseudoAxisEngine
*engine
,
240 HklGeometry
*geometry
,
241 HklDetector
*detector
,
246 HklVector ki
, kf
, Q
, n
;
247 int status
= HKL_SUCCESS
;
249 if (!self
|| !engine
|| !engine
->mode
|| !geometry
|| !detector
|| !sample
){
254 status
= hkl_pseudo_axis_engine_init_func(self
, engine
, geometry
, detector
, sample
);
255 if(status
== HKL_FAIL
)
258 // Compute the constant psi value (to be kept)
259 hkl_vector_init(&hkl
, 1, 0, 0);
262 hkl_source_compute_ki(&geometry
->source
, &ki
);
263 hkl_detector_compute_kf(detector
, geometry
, &kf
);
265 hkl_vector_minus_vector(&Q
, &ki
);
267 if (hkl_vector_is_null(&Q
))
270 hkl_vector_normalize(&Q
); // needed for a problem of precision
272 // compute the intersection of the plan P(kf, ki) and PQ (normal Q)
274 hkl_vector_vectorial_product(&n
, &ki
);
275 hkl_vector_vectorial_product(&n
, &Q
);
277 // compute hkl in the laboratory referentiel
278 // the geometry was already updated in the detector compute kf
279 // for now the 0 holder is the sample holder
280 hkl
.data
[0] = self
->parameters
[0].value
;
281 hkl
.data
[1] = self
->parameters
[1].value
;
282 hkl
.data
[2] = self
->parameters
[2].value
;
283 hkl_vector_times_smatrix(&hkl
, &sample
->UB
);
284 hkl_vector_rotated_quaternion(&hkl
, &geometry
->holders
[0].q
);
286 // project hkl on the plan of normal Q
287 hkl_vector_project_on_plan(&hkl
, &Q
);
289 if (hkl_vector_is_null(&hkl
))
292 // compute the angle beetween hkl and n and store in in the fourth parameter
293 hkl_parameter_set_value(&self
->parameters
[3],
294 hkl_vector_oriented_angle(&n
, &hkl
, &Q
));
301 HklPseudoAxisEngine
*hkl_pseudo_axis_engine_hkl_new(void)
303 HklPseudoAxisEngine
*self
;
305 self
= hkl_pseudo_axis_engine_new("hkl", 3, "h", "k", "l");
308 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[0],
314 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[1],
320 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[2],