Skip to content

Commit c71164a

Browse files
authored
Merge pull request #2395 from mccode-dev/mono_bent_complex_string_parsing
Mono bent complex string parsing
2 parents 5efc621 + bbc48de commit c71164a

3 files changed

Lines changed: 100 additions & 34 deletions

File tree

mcstas-comps/contrib/Monochromator_bent.comp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
* mosaicity: [arcmin] Gaussian mosaicity of the crystal. Always the horizontal mosaicity
4141
* mosaic_anisotropy: [1] Anisotropy of the mosaicity, changes vertical mosaicity to be mosaic_anisotropy*mosaicity
4242
* n_crystals: [#] Number of crystals in your array.
43-
* domainthickness: [mu-m] Thickness of the crystal domains.
43+
* domainthickness: [μm] Thickness of the crystal domains.
4444
* temperature: [K]Temperature of the monochromator in Kelvin.
4545
* optimize: [ ] Flag to tell if the component should optimize for reflections or not.
4646
* x_pos: [vector] x-Position of each crystal

mcstas-comps/contrib/Monochromator_bent_complex.comp

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* This component is a more complex implementation of Monochromator_bent.
1919
* This component only differs in the fact that it allows and forces the user
2020
* to set every single parameter for every single crystal in the crystal array.
21+
* An exception to this rule is the plane of reflection, for which one can
22+
* choose a single plane of reflection, and that will work for all crystals.
2123
*
2224
*
2325
* %Parameters
@@ -27,25 +29,26 @@
2729
* xthickness: [m] Thickness of each crystal without bending.
2830
* radius_x: [m] Radius of the circle the monochromator bends on in the plane. Can be negative.
2931
* radius_y: [m] Radius of the (very large) circle the monochromator bends on as a side effect of the horizontal bending. The code assumes that it is so small that it does not affect the points of intersection appreciatively of the crystal.
30-
* plane_of_reflection: ["Si400"] The plane of reflection from the material. The list of possible reflections can be seen in the source code.
32+
* plane_of_reflection: [string] The plane of reflection from the material. The list of possible reflections can be seen in the source code. Each plane must be separated by a ";", like "Si400;Si111".
3133
* angle_to_cut_horizontal: [degrees] Angle between cut and normal of crystal slab, horizontally
3234
* mosaicity: [arcmin] Gaussian mosaicity of the crystal. Always the horizontal mosaicity
3335
* mosaic_anisotropy: [1] Anisotropy of the mosaicity, changes vertical mosaicity to be mosaic_anisotropy*mosaicity
34-
* n_crystals: [#] Number of crystals in your array.
35-
* domainthickness: [mu-m] Thickness of the crystal domains.
36-
* temperature: [K]Temperature of the monochromator in Kelvin.
37-
* optimize: [ ] Flag to tell if the component should optimize for reflections or not.
36+
* n_crystals: [1] Number of crystals in your array.
37+
* domainthickness: [μm] Thickness of the crystal domains.
38+
* temperature: [K] Temperature of the monochromator in Kelvin.
39+
* optimize: [1] Flag to tell if the component should optimize for reflections or not.
3840
* x_pos: [vector] x-Position of each crystal
3941
* y_pos: [vector] y-Position of each crystal
4042
* z_pos: [vector] z-Position of each crystal
4143
* x_rot: [vector] Rotation around x-axis for each crystal
4244
* y_rot: [vector] Rotation around y-axis for each crystal
4345
* z_rot: [vector] Rotation around z-axis for each crystal NOTE: Rotations happen around x, then y, then z.
44-
* verbose: [ ] Verbosity of the monochromator. Used for debugging.
45-
* draw_as_rectangles: [ ] Draw the monochromators as boxes. DOES NOT WORK WHEN USING _rot parameters.
46+
* verbose: [1] Verbosity of the monochromator. Used for debugging.
47+
* draw_as_rectangles: [1] Draw the monochromators as boxes. DOES NOT WORK WHEN USING _rot parameters.
4648
*
4749
* %L
4850
* <a href="https://doi.org/10.1016/j.nima.2004.04.197">Jan &Scaron;aroun NIM A Volume 529, Issue 1-3 (2004), pp162-165</a>
51+
* <a href="https://doi.org/10.3390/qubs10010006">Christensen, D.L.; Cabeza, S.; Pirling, T.; Lefmann, K.; &Scaron;aroun, J. Simulating Neutron Diffraction from Deformed Mosaic Crystals in McStas. Quantum Beam Sci. 2026, 10, 6. https://doi.org/10.3390/qubs10010006</a>
4952
*
5053
* %E
5154
*******************************************************************************/
@@ -75,7 +78,30 @@ SETTING PARAMETERS (vector zwidth=NULL,
7578
NOACC
7679
// The component is currently "NOACC" only, there are thread race-conditions on GPU
7780

78-
SHARE INHERIT Monochromator_bent
81+
SHARE INHERIT Monochromator_bent EXTEND %{
82+
char *repeat_with_semicolon(const char *src, int n) {
83+
size_t len = strlen(src);
84+
size_t total = n * len + (n - 1) + 1; // repetitions + semicolons + null terminator
85+
86+
char *result = malloc(total);
87+
if (!result) return NULL;
88+
89+
char *p = result;
90+
91+
for (int i = 0; i < n; i++) {
92+
memcpy(p, src, len);
93+
p += len;
94+
95+
if (i < n - 1) {
96+
*p = ';';
97+
p++;
98+
}
99+
}
100+
101+
*p = '\0';
102+
return result;
103+
}
104+
%}
79105
DECLARE
80106
%{
81107
int counter;
@@ -106,19 +132,39 @@ INITIALIZE
106132
mono_arr.verbosity = verbose; // [#]
107133

108134
// Separate the string into individual crystals
109-
int MAX_TOKENS = 6 * n_crystals;
135+
// If no semicolon is present, parse the string as a single plane of reflection
136+
// and apply that to all crystals
110137

111-
char** planes = malloc (n_crystals * sizeof (char*));
112-
if (planes == NULL) {
113-
exit (fprintf (stderr, "Error: memory allocation failed for planes\n"));
138+
char* input_string = NULL;
139+
140+
if (strchr (plane_of_reflection, ';') == NULL && n_crystals > 1) {
141+
// Apply the same plane to all crystals
142+
input_string = repeat_with_semicolon (plane_of_reflection, n_crystals);
143+
} else {
144+
// Use the original string
145+
input_string = strdup (plane_of_reflection);
114146
}
115-
int token_count = 0;
147+
148+
if (!input_string) {
149+
fprintf (stderr, "Error: memory allocation failed\n");
150+
exit (-1);
151+
}
152+
116153
// Remove trailing newline, if any
117-
plane_of_reflection[strcspn (plane_of_reflection, "\n")] = '\0';
154+
input_string[strcspn (input_string, "\n")] = '\0';
155+
156+
// Allocate array for tokens
157+
char** planes = malloc (n_crystals * sizeof (char*));
158+
if (!planes) {
159+
fprintf (stderr, "Error: memory allocation failed for planes\n");
160+
free (input_string);
161+
exit (-1);
162+
}
118163

119164
// Tokenize the string using ';' as delimiter
120-
char* plane = strtok (plane_of_reflection, ";");
121-
while (plane != NULL && token_count < MAX_TOKENS) {
165+
int token_count = 0;
166+
char* plane = strtok (input_string, ";");
167+
while (plane != NULL && token_count < n_crystals) {
122168
planes[token_count++] = plane;
123169
plane = strtok (NULL, ";");
124170
}
@@ -227,6 +273,8 @@ INITIALIZE
227273
mono_arr.crystal[i].lattice_spacing_gradient_field[2][2] = -cos (chi) * tau_size_zero * curvature;
228274
}
229275
free (planes);
276+
free (input_string);
277+
230278
// TODO: This is very gpu unfriendly. Should be changed to depend on OPENACC usage
231279
// Initialize neutron structs values
232280
neutron.beta = (double*)calloc (n_crystals, sizeof (double));

mcstas-comps/examples/Tests_optics/Test_Monochromator_bent_complex/Test_Monochromator_bent_complex.instr

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,20 @@
22
* Instrument: Test_Monochromator_bent_complex
33
*
44
* %Identification
5-
* Written by: Jakob Lass (jakob.lass@psi.ch)
5+
* Written by: Jakob Lass (jakob.lass@psi.ch) and modified by Daniel Lomholt Christensen (daniel.lomholt.2000@gmail.com)
66
* Date: 20250702
77
* Origin: PSI/LSN
88
* %INSTRUMENT_SITE: Tests_optics
9+
* A test instrument that highlights Monochromator Bent complex's capabilities
910
*
11+
* %D
1012
* This is a first draft for the WARP instrument proposal, as created by
1113
* Daniel Gabriel Mazzone (daniel.mazzone@psi.ch) and Jakob Lass
12-
* (jakob.lass@psi.ch). This proposal will include a new component which utilizes
13-
* the marmot geometery. The instrument only looks at the backend of the instrument
14-
* from the sample to the detector, as the guide part of the instrument is not
15-
* fully planned out yet.
16-
*
17-
* %D
18-
* Used as a test instrument to highlight Monochromator Bent complex's capabilities
14+
* (jakob.lass@psi.ch). This instrument introduces how to use the Monochromator_bent_complex
15+
* component in an instrument draft.
1916
*
2017
* %Example: Test_Monochromator_bent_complex.instr mos=60 Detector: E_PSD_mon_end_I=0.000215194
18+
* %Example: Test_Monochromator_bent_complex.instr mos=60 use_single_plane=1 Detector: E_PSD_mon_end_I=0.000215194
2119
*
2220
* %Parameters
2321
* sample_x: [m] Source horz illumination
@@ -28,6 +26,7 @@
2826
* det_rot: [m] Detector rotation
2927
* mos: [arcmin] Monochromator mosaicity
3028
* extra: [deg] Perturbation rotation angle
29+
* use_single_plane: [flag] Flag indicating whether the crystal should be instantiated with a single plane of reflection, instead of 92 planes
3130
*
3231
* %End
3332
*******************************************************************************/
@@ -39,7 +38,8 @@ double L1=2.47143,
3938
double Ld=2,
4039
double det_rot=-6.00000,
4140
double mos=60,
42-
double extra=0)
41+
double extra=0,
42+
int use_single_plane = 0)
4343

4444
DECLARE
4545
%{
@@ -62,7 +62,8 @@ double z_pos[92];
6262
double x_rot[92];
6363
double y_rot[92];
6464
double z_rot[92];
65-
char input_planes[552];
65+
char *input_planes;
66+
6667
double z_test[2];
6768
double y_test[2];
6869
double z_test1[2];
@@ -157,13 +158,30 @@ double y_rots[92] = {
157158
28.949037231991614,29.10800625807111,29.263677094830634,29.415964179519083,29.5647341124584,
158159
29.70985123904334,29.85123876074083,29.988616895395413,30.1218449608264,30.374816895175396,
159160
30.60585732884762,30.807078570093147};
160-
strcpy(input_planes, "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
161-
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
162-
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
163-
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
164-
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
165-
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
166-
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111");
161+
if (use_single_plane){
162+
163+
input_planes = malloc(5*sizeof(char));
164+
if (!input_planes){
165+
printf("\nError Mallocing input planes! Exiting \n");
166+
exit(1);
167+
}
168+
input_planes = "Si111";
169+
} else {
170+
input_planes = malloc(92*5*sizeof(char) + 92*sizeof(char));
171+
if (!input_planes){
172+
printf("\nError Mallocing input planes! Exiting \n");
173+
exit(1);
174+
}
175+
strcpy(input_planes, "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
176+
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
177+
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
178+
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
179+
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
180+
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;"
181+
"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111");
182+
}
183+
184+
167185
for (int i=0; i<92; i++){
168186
rad_y[i]=0;
169187
xthic[i] = 0.0005;

0 commit comments

Comments
 (0)