diff --git a/mcstas-comps/contrib/Monochromator_bent_complex.comp b/mcstas-comps/contrib/Monochromator_bent_complex.comp index 7d960fa666..8048576f71 100755 --- a/mcstas-comps/contrib/Monochromator_bent_complex.comp +++ b/mcstas-comps/contrib/Monochromator_bent_complex.comp @@ -18,6 +18,8 @@ * This component is a more complex implementation of Monochromator_bent. * This component only differs in the fact that it allows and forces the user * to set every single parameter for every single crystal in the crystal array. +* An exception to this rule is the plane of reflection, for which one can +* choose a single plane of reflection, and that will work for all crystals. * * * %Parameters @@ -27,25 +29,26 @@ * xthickness: [m] Thickness of each crystal without bending. * radius_x: [m] Radius of the circle the monochromator bends on in the plane. Can be negative. * 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. -* plane_of_reflection: ["Si400"] The plane of reflection from the material. The list of possible reflections can be seen in the source code. +* 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". * angle_to_cut_horizontal: [degrees] Angle between cut and normal of crystal slab, horizontally * mosaicity: [arcmin] Gaussian mosaicity of the crystal. Always the horizontal mosaicity * mosaic_anisotropy: [1] Anisotropy of the mosaicity, changes vertical mosaicity to be mosaic_anisotropy*mosaicity -* n_crystals: [#] Number of crystals in your array. -* domainthickness: [mu-m] Thickness of the crystal domains. -* temperature: [K]Temperature of the monochromator in Kelvin. -* optimize: [ ] Flag to tell if the component should optimize for reflections or not. +* n_crystals: [1] Number of crystals in your array. +* domainthickness: [μm] Thickness of the crystal domains. +* temperature: [K] Temperature of the monochromator in Kelvin. +* optimize: [1] Flag to tell if the component should optimize for reflections or not. * x_pos: [vector] x-Position of each crystal * y_pos: [vector] y-Position of each crystal * z_pos: [vector] z-Position of each crystal * x_rot: [vector] Rotation around x-axis for each crystal * y_rot: [vector] Rotation around y-axis for each crystal * z_rot: [vector] Rotation around z-axis for each crystal NOTE: Rotations happen around x, then y, then z. -* verbose: [ ] Verbosity of the monochromator. Used for debugging. -* draw_as_rectangles: [ ] Draw the monochromators as boxes. DOES NOT WORK WHEN USING _rot parameters. +* verbose: [1] Verbosity of the monochromator. Used for debugging. +* draw_as_rectangles: [1] Draw the monochromators as boxes. DOES NOT WORK WHEN USING _rot parameters. * * %L * Jan Šaroun NIM A Volume 529, Issue 1-3 (2004), pp162-165 +* Christensen, D.L.; Cabeza, S.; Pirling, T.; Lefmann, K.; Šaroun, J. Simulating Neutron Diffraction from Deformed Mosaic Crystals in McStas. Quantum Beam Sci. 2026, 10, 6. https://doi.org/10.3390/qubs10010006 * * %E *******************************************************************************/ @@ -75,7 +78,30 @@ SETTING PARAMETERS (vector zwidth=NULL, NOACC // The component is currently "NOACC" only, there are thread race-conditions on GPU -SHARE INHERIT Monochromator_bent +SHARE INHERIT Monochromator_bent EXTEND %{ +char *repeat_with_semicolon(const char *src, int n) { + size_t len = strlen(src); + size_t total = n * len + (n - 1) + 1; // repetitions + semicolons + null terminator + + char *result = malloc(total); + if (!result) return NULL; + + char *p = result; + + for (int i = 0; i < n; i++) { + memcpy(p, src, len); + p += len; + + if (i < n - 1) { + *p = ';'; + p++; + } + } + + *p = '\0'; + return result; +} +%} DECLARE %{ int counter; @@ -106,19 +132,39 @@ INITIALIZE mono_arr.verbosity = verbose; // [#] // Separate the string into individual crystals - int MAX_TOKENS = 6 * n_crystals; + // If only 5 characters are given, and number of crystals are larger than 1, + // assume that they want to use the same plane on all the crystals. - char** planes = malloc (n_crystals * sizeof (char*)); - if (planes == NULL) { - exit (fprintf (stderr, "Error: memory allocation failed for planes\n")); + char* input_string = NULL; + + if (strlen (plane_of_reflection) == 5 && n_crystals > 1) { + // Apply the same plane to all crystals + input_string = repeat_with_semicolon (plane_of_reflection, n_crystals); + } else { + // Use the original string + input_string = strdup (plane_of_reflection); } - int token_count = 0; + + if (!input_string) { + fprintf (stderr, "Error: memory allocation failed\n"); + exit (-1); + } + // Remove trailing newline, if any - plane_of_reflection[strcspn (plane_of_reflection, "\n")] = '\0'; + input_string[strcspn (input_string, "\n")] = '\0'; + + // Allocate array for tokens + char** planes = malloc (n_crystals * sizeof (char*)); + if (!planes) { + fprintf (stderr, "Error: memory allocation failed for planes\n"); + free (input_string); + exit (-1); + } // Tokenize the string using ';' as delimiter - char* plane = strtok (plane_of_reflection, ";"); - while (plane != NULL && token_count < MAX_TOKENS) { + int token_count = 0; + char* plane = strtok (input_string, ";"); + while (plane != NULL && token_count < n_crystals) { planes[token_count++] = plane; plane = strtok (NULL, ";"); } @@ -227,6 +273,8 @@ INITIALIZE mono_arr.crystal[i].lattice_spacing_gradient_field[2][2] = -cos (chi) * tau_size_zero * curvature; } free (planes); + free (input_string); + // TODO: This is very gpu unfriendly. Should be changed to depend on OPENACC usage // Initialize neutron structs values neutron.beta = (double*)calloc (n_crystals, sizeof (double)); diff --git a/mcstas-comps/examples/Tests_optics/Test_Monochromator_bent_complex/Test_Monochromator_bent_complex.instr b/mcstas-comps/examples/Tests_optics/Test_Monochromator_bent_complex/Test_Monochromator_bent_complex.instr index 785a106b7c..99ad23a54f 100644 --- a/mcstas-comps/examples/Tests_optics/Test_Monochromator_bent_complex/Test_Monochromator_bent_complex.instr +++ b/mcstas-comps/examples/Tests_optics/Test_Monochromator_bent_complex/Test_Monochromator_bent_complex.instr @@ -18,6 +18,7 @@ * Used as a test instrument to highlight Monochromator Bent complex's capabilities * * %Example: Test_Monochromator_bent_complex.instr mos=60 Detector: E_PSD_mon_end_I=0.000215194 +* %Example: Test_Monochromator_bent_complex.instr mos=60 use_single_plane=1 Detector: E_PSD_mon_end_I=0.000215194 * * %Parameters * sample_x: [m] Source horz illumination @@ -39,7 +40,8 @@ double L1=2.47143, double Ld=2, double det_rot=-6.00000, double mos=60, -double extra=0) +double extra=0, +int use_single_plane = 0) DECLARE %{ @@ -62,7 +64,8 @@ double z_pos[92]; double x_rot[92]; double y_rot[92]; double z_rot[92]; -char input_planes[552]; +char *input_planes; + double z_test[2]; double y_test[2]; double z_test1[2]; @@ -157,13 +160,30 @@ double y_rots[92] = { 28.949037231991614,29.10800625807111,29.263677094830634,29.415964179519083,29.5647341124584, 29.70985123904334,29.85123876074083,29.988616895395413,30.1218449608264,30.374816895175396, 30.60585732884762,30.807078570093147}; -strcpy(input_planes, "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" -"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" -"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" -"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" -"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" -"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" -"Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111"); +if (use_single_plane){ + + input_planes = malloc(5*sizeof(char)); + if (!input_planes){ + printf("\nError Mallocing input planes! Exiting \n"); + exit(1); + } + input_planes = "Si111"; +} else { + input_planes = malloc(92*5*sizeof(char) + 92*sizeof(char)); + if (!input_planes){ + printf("\nError Mallocing input planes! Exiting \n"); + exit(1); + } + strcpy(input_planes, "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" + "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" + "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" + "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" + "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" + "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;" + "Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111;Si111"); +} + + for (int i=0; i<92; i++){ rad_y[i]=0; xthic[i] = 0.0005;