<jupyter_start><jupyter_text>Guide simulation exerciseIn this notebook we set up a simulation of a simple guide including calculation of the brilliance transfer. The task of the student is to adjust the guide and parameters to improve the beam characteristics and brilliance transfer.   Overview of guide to be simulatedThe guide to be simulated is shown on the figure below. It consists of a tapered section called *tapered*, a straight section called *guide* and a elliptic focusing section called *focusing*. The geometry of the guide will be described with a number of parameters which are shown below the guide. The focal points of the elliptic section are described as distances from the start and end of the guide section, where positive values are outside the guide element.  Writing the simulationWe start by loading our python packages and defining an instrument object.<jupyter_code>import numpy as np
from mcstasscript.interface import instr, functions, plotter
instrument = instr.McStas_instr("guide_exercise", input_path="run_folder")<jupyter_output><empty_output><jupyter_text>Setting our sample parametersHere we define parameters concerning our sample, these can be variables in python as they do not need to change at run time.<jupyter_code>sample_width = 0.01 # m
sample_height = 0.01 # m
max_divergence_horizontal = 1.0 # deg
max_divergence_vertical = 0.8 # deg
sample_guide_distance = 0.5 # m<jupyter_output><empty_output><jupyter_text>Setting up the instrumentHere a source and the first guide element is defined along with some input parameters to control the guide geometry.<jupyter_code># Set up a source
instrument.add_parameter("wavelength", value=3, comment="[AA]")

src = instrument.add_component("source", "Source_div")
src.xwidth = 0.1
src.yheight = 0.05
src.lambda0 = "wavelength"
src.dlambda = 0.01
src.focus_aw = 2*max_divergence_horizontal
src.focus_ah = 2*max_divergence_vertical
src.flux = 1E13

# Opening of first tappered section
instrument.add_parameter("entrance_width", value=0.05, comment="[m]")
instrument.add_parameter("entrance_height", value=0.05, comment="[m]")

# divergence reference monitor
ref_mon = instrument.add_component("ref_mon", "Divergence_monitor")
ref_mon.set_AT([0,0,0.01], RELATIVE=src)

ref_mon.xwidth = sample_width
ref_mon.yheight = sample_height
ref_mon.maxdiv_h = max_divergence_horizontal
ref_mon.maxdiv_v = max_divergence_vertical
ref_mon.nh = 80
ref_mon.nv = 100
ref_mon.filename = '"reference_divergence.dat"'
ref_mon.restore_neutron = 1

# Start and end of straight section
instrument.add_parameter("straight_width", value=0.05, comment="[m]")
instrument.add_parameter("straight_height", value=0.05, comment="[m]")

# Tappered guide section starting 2 m from moderator
tapered = instrument.add_component("tappered", "Guide_gravity")
tapered.set_AT([0, 0, 2], RELATIVE=src)

tapered.w1 = "entrance_width"
tapered.h1 = "entrance_height"
tapered.w2 = "straight_width"
tapered.h2 = "straight_height"
tapered.l = 8.0
tapered.m = 3.5
tapered.G = -9.82<jupyter_output><empty_output><jupyter_text>Task 1We want to continue with a straight guide that has the same entrance and exit dimensions, these are already defined as parameters *straight_width* and *straight_height*. The object should be called guide in python as shown below, as it is used as a reference for the next component. Give the guide a length of 30 meters and an m coating of 2.0. It is important it is placed just after the exit of the tappered guide, remember you can access the length of the tapered guide as *tapered.l*.<jupyter_code># Add your code below
#guide = instrument.add_component("guide", ...<jupyter_output><empty_output><jupyter_text>Finishing the instrumentThe guide is finished with a 6 m long elliptic section that connects to the straight guide. The focal lengths relative to the start and end of the guide are set up as input parameters, positive values means focal points outside of the guide element. At the end we place the sample, here a monitor showing the divergence within the requested divergence interval.<jupyter_code># Elliptic focusing section, starting 1 mm after end of straight
focusing = instrument.add_component("focusing", "Elliptic_guide_gravity")
focusing.set_AT([0, 0, guide.l + 1E-3], RELATIVE=guide)

instrument.add_parameter("focal_length_in_x", value=2, comment="[m]")
instrument.add_parameter("focal_length_in_y", value=2, comment="[m]")
instrument.add_parameter("focal_length_out_x", value=0.5, comment="[m]")
instrument.add_parameter("focal_length_out_y", value=0.5, comment="[m]")

focusing.dimensionsAt = '"entrance"'
focusing.xwidth = "straight_width"
focusing.yheight = "straight_height"
focusing.m = 4.0
focusing.l = 6.0
focusing.linxw = "focal_length_in_x"
focusing.linyh = "focal_length_in_y"
focusing.loutxw = "focal_length_out_x"
focusing.loutyh = "focal_length_out_y"

# Sample monitor needs to be a copy of the reference monitor, so a copy is made to avoid differences
sample_mon = instrument.copy_component("sample_mon", "ref_mon")
sample_mon.set_AT([0, 0, focusing.l + sample_guide_distance], RELATIVE=focusing)
sample_mon.filename = '"sample_mon.dat"'<jupyter_output><empty_output><jupyter_text>Task 2Run the simulation and adjust the parameters manually to maximize the brilliance transfer of the guide at a chosen wavelength. Let us first look at the available parameters.<jupyter_code>instrument.show_parameters()<jupyter_output><empty_output><jupyter_text>A history of the brilliance transfer results is kept, this can be reset by running the cell below.<jupyter_code># Run this cell to reset history
BT_history = []<jupyter_output><empty_output><jupyter_text>The cell below sets up the desired parameters and runs the simulation. The results are plotted and the brilliance transfer calculated. The brilliance transfer result can only be trusted if the simulated intensity on the reference monitor is uniform, if for example a very large sample is chosen, this would not be the case and further considerations would be necessary. The history of simulated brilliance transfers are plotted to help track progress.<jupyter_code>parameters = {"wavelength": 3.0,
              "entrance_width": 0.05, "entrance_height": 0.05,
              "straight_width": 0.05, "straight_height": 0.05,
              "focal_length_in_x": 2, "focal_length_in_y": 2, 
              "focal_length_in_x": 0.5, "focal_length_in_y": 0.5}

data = instrument.run_full_instrument(ncount=1E6, foldername="data_folder/guide_exercise",
                                      increment_folder_name=True,
                                      parameters=parameters)

# Plot the data
plotter.make_sub_plot(data)

# Find reference monitor and calculate total intensity
ref = functions.name_search("ref_mon", data)
ref_I = ref.Intensity
ref_total_I = np.sum(ref_I)

# Find sample monitor and calculate total intensity
sample = functions.name_search("sample_mon", data)
sample_I = sample.Intensity
sample_total_I = np.sum(sample_I)

# Calculate brilliance transfer and append to history
BT_percentage = 100*sample_total_I/ref_total_I
BT_history.append(BT_percentage)

# Print the found brilliance transfer
print("Found brilliance transfer = ", BT_percentage, "%")

# Plot the history
import matplotlib.pyplot as plt
plt.figure()
plt.plot(BT_history, "-o")
plt.xlabel("Attempt number")
plt.ylabel("BT in %")
plt.show()<jupyter_output><empty_output><jupyter_text>Task 3 (Optional)Since the intensity is available in numpy arrays, *ref_I* and *sample_I*, one can plot the 1D horizontal and vertical brilliance transfer by summing over one dimension and normalizing. Below the task is started by setting up the axis for horizontal and vertical divergence.**Hint:** The np.sum function can sum over different directions in the data using the rank of the desired direction as the second input, for example np.sum(data, 0).<jupyter_code>h_div_limits = sample.metadata.limits[0:2]
v_div_limits = sample.metadata.limits[2:4]

h_div_axis = np.linspace(h_div_limits[0], h_div_limits[1], sample_I.shape[1])
v_div_axis = np.linspace(v_div_limits[0], v_div_limits[1], sample_I.shape[0])

# Add your code below<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08476853548308294, 'fraction_numerical': 0.01551239770367656, 'mean_word_length': 5.684081632653061, 'pattern_counts': {'":': 9, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '149773', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2589, 'n_tokens_neox': 2452, 'n_words': 843, 'path': 'notebooks/5_McStas/Exercise_1_guide_simulation.ipynb', 'repo_name': 'celinedurniak/python-course-ikon', 'size': '8187'}