1 #include <gsl/gsl_math.h>
2 #include <gsl/gsl_vector.h>
3 #include <gsl/gsl_sf_trig.h>
5 #include <hkl/hkl-pseudoaxis.h>
6 #include <hkl/hkl-pseudoaxis-common-psi.h>
8 static int psi(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
11 HklVector dhkl0
, hkl1
;
12 HklVector ki
, kf
, Q
, n
;
14 HklPseudoAxisEngine
*engine
;
15 HklPseudoAxisEngineGetSetPsi
*getsetpsi
;
19 double const *x_data
= gsl_vector_const_ptr(x
, 0);
20 double *f_data
= gsl_vector_ptr(f
, 0);
23 getsetpsi
= (HklPseudoAxisEngineGetSetPsi
*)engine
->getset
;
24 psi
= &engine
->pseudoAxes
[0];
26 // update the workspace from x;
27 for(i
=0; i
<engine
->axes_len
; ++i
) {
28 HklAxis
*axis
= engine
->axes
[i
];
29 axis
->config
.value
= x_data
[i
];
30 axis
->config
.dirty
= 1;
32 hkl_geometry_update(engine
->geometry
);
35 hkl_source_compute_ki(&engine
->geometry
->source
, &ki
);
36 hkl_detector_compute_kf(engine
->detector
, engine
->geometry
, &kf
);
38 hkl_vector_minus_vector(&Q
, &ki
);
39 if (hkl_vector_is_null(&Q
)){
40 f_data
[0] = dhkl0
.data
[0];
41 f_data
[1] = dhkl0
.data
[1];
42 f_data
[2] = dhkl0
.data
[2];
46 // for now the 0 holder is the sample holder.
47 holder
= &engine
->geometry
->holders
[0];
48 hkl_quaternion_to_smatrix(&holder
->q
, &RUB
);
49 hkl_matrix_times_smatrix(&RUB
, &engine
->sample
->UB
);
52 hkl_matrix_solve(&RUB
, &dhkl0
, &Q
);
53 hkl_vector_minus_vector(&dhkl0
, &getsetpsi
->hkl0
);
55 // compute the intersection of the plan P(kf, ki) and PQ (normal Q)
57 * now that dhkl0 have been computed we can use a
58 * normalized Q to compute n and psi
60 hkl_vector_normalize(&Q
);
62 hkl_vector_vectorial_product(&n
, &ki
);
63 hkl_vector_vectorial_product(&n
, &Q
);
65 // compute hkl1 in the laboratory referentiel
66 // for now the 0 holder is the sample holder.
67 hkl1
.data
[0] = engine
->getset
->parameters
[0].value
;
68 hkl1
.data
[1] = engine
->getset
->parameters
[1].value
;
69 hkl1
.data
[2] = engine
->getset
->parameters
[2].value
;
70 hkl_vector_times_smatrix(&hkl1
, &engine
->sample
->UB
);
71 hkl_vector_rotated_quaternion(&hkl1
, &engine
->geometry
->holders
[0].q
);
73 // project hkl1 on the plan of normal Q
74 hkl_vector_project_on_plan(&hkl1
, &Q
);
75 if (hkl_vector_is_null(&hkl1
)){ // hkl1 colinear with Q
76 f_data
[0] = dhkl0
.data
[0];
77 f_data
[1] = dhkl0
.data
[1];
78 f_data
[2] = dhkl0
.data
[2];
81 f_data
[0] = dhkl0
.data
[0];
82 f_data
[1] = dhkl0
.data
[1];
83 f_data
[2] = dhkl0
.data
[2];
84 f_data
[3] = psi
->config
.value
- hkl_vector_oriented_angle(&n
, &hkl1
, &Q
);
90 int hkl_pseudo_axis_engine_get_set_init_psi_real(HklPseudoAxisEngine
*engine
,
91 HklGeometry
*geometry
,
92 HklDetector
const *detector
,
93 HklSample
const *sample
)
95 int status
= HKL_SUCCESS
;
99 HklPseudoAxisEngineGetSetPsi
*self
;
100 HklPseudoAxisEngineGetSet
*base
;
103 status
= hkl_pseudo_axis_engine_init_func(engine
, geometry
, detector
, sample
);
104 if (status
== HKL_FAIL
)
107 self
= (HklPseudoAxisEngineGetSetPsi
*)engine
->getset
;
109 // update the geometry internals
110 hkl_geometry_update(geometry
);
113 // for now the 0 holder is the sample holder.
114 holder
= &geometry
->holders
[0];
115 hkl_quaternion_to_smatrix(&holder
->q
, &RUB
);
116 hkl_matrix_times_smatrix(&RUB
, &sample
->UB
);
119 hkl_source_compute_ki(&geometry
->source
, &ki
);
120 hkl_detector_compute_kf(detector
, geometry
, &self
->Q0
);
121 hkl_vector_minus_vector(&self
->Q0
, &ki
);
122 if (hkl_vector_is_null(&self
->Q0
))
126 hkl_matrix_solve(&RUB
, &self
->hkl0
, &self
->Q0
);
131 int hkl_pseudo_axis_engine_get_set_get_psi_real(HklPseudoAxisEngine
*engine
,
132 HklGeometry
*geometry
,
133 HklDetector
const *detector
,
134 HklSample
const *sample
)
136 int status
= HKL_SUCCESS
;
138 if (!engine
|| !engine
->getset
|| !geometry
|| !detector
|| !sample
){
149 HklPseudoAxisEngineGetSetPsi
*self
;
150 HklPseudoAxisEngineGetSet
*base
;
152 self
= (HklPseudoAxisEngineGetSetPsi
*)engine
->getset
;
153 base
= engine
->getset
;
156 hkl_source_compute_ki(&geometry
->source
, &ki
);
157 hkl_detector_compute_kf(detector
, geometry
, &kf
);
159 hkl_vector_minus_vector(&Q
, &ki
);
160 if (hkl_vector_is_null(&Q
))
163 hkl_vector_normalize(&Q
); // needed for a problem of precision
165 // compute the intersection of the plan P(kf, ki) and PQ (normal Q)
167 hkl_vector_vectorial_product(&n
, &ki
);
168 hkl_vector_vectorial_product(&n
, &Q
);
170 // compute hkl1 in the laboratory referentiel
171 // the geometry was already updated in the detector compute kf
172 // for now the 0 holder is the sample holder.
173 hkl1
.data
[0] = base
->parameters
[0].value
;
174 hkl1
.data
[1] = base
->parameters
[1].value
;
175 hkl1
.data
[2] = base
->parameters
[2].value
;
176 hkl_vector_times_smatrix(&hkl1
, &sample
->UB
);
177 hkl_vector_rotated_quaternion(&hkl1
, &geometry
->holders
[0].q
);
179 // project hkl1 on the plan of normal Q
180 hkl_vector_project_on_plan(&hkl1
, &Q
);
182 if (hkl_vector_is_null(&hkl1
))
185 // compute the angle beetween hkl1 and n
186 engine
->pseudoAxes
[0].config
.value
= hkl_vector_oriented_angle(&n
, &hkl1
, &Q
);
192 int hkl_pseudo_axis_engine_get_set_set_psi_real(HklPseudoAxisEngine
*engine
,
193 HklGeometry
*geometry
,
194 HklDetector
*detector
,
197 hkl_pseudoAxeEngine_prepare_internal(engine
, geometry
, detector
,
200 return hkl_pseudoAxeEngine_solve_function(engine
, psi
);