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 * Jens Krüger <Jens.Krueger@frm2.tum.de>
24 #include <hkl/hkl-pseudoaxis.h>
25 #include <hkl/hkl-pseudoaxis-common.h>
26 #include <hkl/hkl-pseudoaxis-common-q.h>
27 #include <hkl/hkl-pseudoaxis-auto.h>
28 #include <gsl/gsl_sf_trig.h>
34 static int q(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
42 HklPseudoAxisEngine
*engine
;
44 x_data
= gsl_vector_const_ptr(x
, 0);
45 f_data
= gsl_vector_ptr(f
, 0);
48 /* update the workspace from x */
49 for(i
=0; i
<HKL_LIST_LEN(engine
->axes
); ++i
)
50 hkl_axis_set_value(engine
->axes
[i
], x_data
[i
]);
51 hkl_geometry_update(engine
->geometry
);
53 q0
= ((HklParameter
*)engine
->pseudoAxes
[0])->value
;
55 tth
= gsl_sf_angle_restrict_symm(x_data
[0]);
56 q
= 2 * HKL_TAU
/ hkl_source_get_wavelength(&engine
->geometry
->source
) * sin(tth
/2.);
63 static int hkl_pseudo_axis_engine_mode_get_q_real(HklPseudoAxisEngineMode
*self
,
64 HklPseudoAxisEngine
*engine
,
65 HklGeometry
*geometry
,
66 HklDetector
*detector
,
73 HklInterval range
= {0, 0};
75 HklParameter
*parameter
;
77 wavelength
= hkl_source_get_wavelength(&geometry
->source
);
78 hkl_source_compute_ki(&geometry
->source
, &ki
);
79 hkl_detector_compute_kf(detector
, geometry
, &kf
);
80 theta
= hkl_vector_angle(&ki
, &kf
) / 2.;
82 hkl_vector_vectorial_product(&ki
, &kf
);
86 q
= 2 * HKL_TAU
/ wavelength
* sin(theta
);
89 parameter
= (HklParameter
*)(engine
->pseudoAxes
[0]);
90 hkl_parameter_set_value(parameter
, q
);
91 hkl_parameter_set_range(parameter
, range
.min
, range
.max
);
96 HklPseudoAxisEngine
*hkl_pseudo_axis_engine_q_new(void)
98 HklPseudoAxisEngine
*self
;
99 HklPseudoAxisEngineMode
*mode
;
101 self
= hkl_pseudo_axis_engine_new("q", 1, "q");
104 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[0],
110 mode
= hkl_pseudo_axis_engine_mode_new(
113 hkl_pseudo_axis_engine_mode_get_q_real
,
114 hkl_pseudo_axis_engine_mode_set_real
,
118 hkl_pseudo_axis_engine_add_mode(self
, mode
);
121 hkl_pseudo_axis_engine_select_mode(self
, 0);
130 static int q2(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
134 double alpha0
, alpha
;
135 double wavelength
, theta
;
136 double const *x_data
;
138 HklPseudoAxisEngine
*engine
;
140 HklVector X
= {{1, 0, 0}};
142 x_data
= gsl_vector_const_ptr(x
, 0);
143 f_data
= gsl_vector_ptr(f
, 0);
146 /* update the workspace from x */
147 for(i
=0; i
<HKL_LIST_LEN(engine
->axes
); ++i
)
148 hkl_axis_set_value(engine
->axes
[i
], x_data
[i
]);
149 hkl_geometry_update(engine
->geometry
);
151 q0
= ((HklParameter
*)engine
->pseudoAxes
[0])->value
;
152 alpha0
= ((HklParameter
*)engine
->pseudoAxes
[1])->value
;
154 wavelength
= hkl_source_get_wavelength(&engine
->geometry
->source
);
155 hkl_source_compute_ki(&engine
->geometry
->source
, &ki
);
156 hkl_detector_compute_kf(engine
->detector
, engine
->geometry
, &kf
);
157 theta
= hkl_vector_angle(&ki
, &kf
) / 2.;
159 q
= 2 * HKL_TAU
/ wavelength
* sin(theta
);
161 /* project kf on the x plan to compute alpha */
162 hkl_vector_project_on_plan(&kf
, &X
);
163 alpha
= atan2(kf
.data
[2], kf
.data
[1]);
166 f_data
[1] = alpha0
- alpha
;
172 static int hkl_pseudo_axis_engine_mode_get_q2_real(HklPseudoAxisEngineMode
*self
,
173 HklPseudoAxisEngine
*engine
,
174 HklGeometry
*geometry
,
175 HklDetector
*detector
,
182 HklVector x
= {{1, 0, 0}};
184 HklParameter
*parameter
;
186 wavelength
= hkl_source_get_wavelength(&geometry
->source
);
187 hkl_source_compute_ki(&geometry
->source
, &ki
);
188 hkl_detector_compute_kf(detector
, geometry
, &kf
);
189 theta
= hkl_vector_angle(&ki
, &kf
) / 2.;
191 q
= 2 * HKL_TAU
/ wavelength
* sin(theta
);
193 /* project kf on the x plan to compute alpha */
194 hkl_vector_project_on_plan(&kf
, &x
);
195 alpha
= atan2(kf
.data
[2], kf
.data
[1]);
198 parameter
= (HklParameter
*)(engine
->pseudoAxes
[0]);
199 hkl_parameter_set_value(parameter
, q
);
202 parameter
= (HklParameter
*)(engine
->pseudoAxes
[1]);
203 hkl_parameter_set_value(parameter
, alpha
);
204 hkl_parameter_set_range(parameter
, -M_PI
, M_PI
);
209 HklPseudoAxisEngine
*hkl_pseudo_axis_engine_q2_new(void)
211 HklPseudoAxisEngine
*self
;
212 HklPseudoAxisEngineMode
*mode
;
214 self
= hkl_pseudo_axis_engine_new("q2", 2, "q", "alpha");
217 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[0],
224 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[1],
228 &hkl_unit_angle_rad
, &hkl_unit_angle_deg
);
231 mode
= hkl_pseudo_axis_engine_mode_new(
234 hkl_pseudo_axis_engine_mode_get_q2_real
,
235 hkl_pseudo_axis_engine_mode_set_real
,
238 (size_t)2, "gamma", "delta");
239 hkl_pseudo_axis_engine_add_mode(self
, mode
);
242 hkl_pseudo_axis_engine_select_mode(self
, 0);