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>
21 * Jens Krüger <Jens.Krueger@frm2.tum.de>
23 #include <gsl/gsl_errno.h> // for ::GSL_SUCCESS
24 #include <gsl/gsl_sf_trig.h> // for gsl_sf_angle_restrict_symm
25 #include <gsl/gsl_sys.h> // for gsl_isnan
26 #include <gsl/gsl_vector_double.h> // for gsl_vector
27 #include <math.h> // for sin, atan2, signbit
28 #include <stdlib.h> // for free
29 #include "hkl-detector-private.h" // for hkl_detector_compute_kf
30 #include "hkl-geometry-private.h" // for _HklGeometry, HklHolder
31 #include "hkl-macros-private.h" // for HKL_MALLOC
32 #include "hkl-parameter-private.h" // for _HklParameter, etc
33 #include "hkl-pseudoaxis-auto-private.h" // for HklFunction, etc
34 #include "hkl-pseudoaxis-common-tth-private.h" // for HklEngineQ2, etc
35 #include "hkl-pseudoaxis-private.h" // for _HklEngine, etc
36 #include "hkl-source-private.h" // for hkl_source_compute_ki, etc
37 #include "hkl-vector-private.h" // for HklVector, hkl_vector_angle, etc
38 #include "hkl.h" // for HklEngine, HklParameter, etc
39 #include "hkl/ccan/array_size/array_size.h" // for ARRAY_SIZE
40 #include "hkl/ccan/container_of/container_of.h" // for container_of
41 #include "hkl/ccan/darray/darray.h" // for darray_item
55 static void _tth2(HklGeometry
*geometry
, HklDetector
*detector
,
56 double *tth
, double *alpha
)
59 static HklVector x
= {
63 ki
= hkl_geometry_ki_get(geometry
);
64 kf
= hkl_geometry_kf_get(geometry
, detector
);
65 *tth
= hkl_vector_angle(&ki
, &kf
);
67 /* project kf on the x plan to compute alpha */
68 hkl_vector_project_on_plan(&kf
, &x
);
70 *alpha
= atan2(kf
.data
[2], kf
.data
[1]);
74 static int _tth2_func(const gsl_vector
*x
, void *params
, gsl_vector
*f
)
76 HklEngine
*engine
= params
;
77 const HklEngineTth2
*engine_tth2
= container_of(engine
, HklEngineTth2
, engine
);
81 CHECK_NAN(x
->data
, x
->size
);
83 /* update the workspace from x */
84 set_geometry_axes(engine
, x
->data
);
86 _tth2(engine
->geometry
, engine
->detector
, &tth
, &alpha
);
88 f
->data
[0] = engine_tth2
->tth
->_value
- tth
;
89 f
->data
[1] = engine_tth2
->alpha
->_value
- alpha
;
94 static const HklFunction tth2_func
= {
95 .function
= _tth2_func
,
99 static int get_tth2_real(HklMode
*self
,
101 HklGeometry
*geometry
,
102 HklDetector
*detector
,
106 HklEngineTth2
*engine_tth2
= container_of(engine
, HklEngineTth2
, engine
);
108 _tth2(geometry
, detector
,
109 &engine_tth2
->tth
->_value
,
110 &engine_tth2
->alpha
->_value
);
115 static HklMode
*mode_tth2(void)
117 static const char* axes
[] = {"gamma", "delta"};
118 static const HklFunction
*functions
[] = {&tth2_func
};
119 static const HklModeAutoInfo info
= {
120 HKL_MODE_AUTO_INFO("tth2", axes
, axes
, functions
),
122 static const HklModeOperations operations
= {
123 HKL_MODE_OPERATIONS_AUTO_DEFAULTS
,
124 .get
= get_tth2_real
,
127 return hkl_mode_auto_new(&info
, &operations
, TRUE
);
130 static void hkl_engine_tth2_free_real(HklEngine
*base
)
132 HklEngineTth2
*self
= container_of(base
, HklEngineTth2
, engine
);
133 hkl_engine_release(&self
->engine
);
137 HklEngine
*hkl_engine_tth2_new(HklEngineList
*engines
)
139 HklEngineTth2
*self
= g_new(HklEngineTth2
, 1);
142 static const HklParameter tth
= {
143 HKL_PARAMETER_DEFAULTS_ANGLE
, .name
="tth",
144 .description
= "the $2 \\theta$ angle",
146 static const HklParameter alpha
= {
147 HKL_PARAMETER_DEFAULTS_ANGLE
, .name
= "alpha",
148 .description
= "angle of the projection of $\\vec{q}$ on the $yOz$ plan and $\\vec{y}$",
150 static const HklParameter
*pseudo_axes
[] = {&tth
, &alpha
};
151 static const HklEngineInfo info
= {
152 HKL_ENGINE_INFO("tth2",
154 HKL_ENGINE_DEPENDENCIES_AXES
),
156 static const HklEngineOperations operations
= {
157 HKL_ENGINE_OPERATIONS_DEFAULTS
,
158 .free
=hkl_engine_tth2_free_real
,
161 hkl_engine_init(&self
->engine
, &info
, &operations
, engines
);
162 self
->tth
= register_pseudo_axis(&self
->engine
, engines
, &tth
);
163 self
->alpha
= register_pseudo_axis(&self
->engine
, engines
, &alpha
);
167 hkl_engine_add_mode(&self
->engine
, mode
);
168 hkl_engine_mode_set(&self
->engine
, mode
);
170 return &self
->engine
;