{ "cells": [ { "cell_type": "markdown", "id": "smooth-monaco", "metadata": {}, "source": [ "# Parameters and variables\n", "At the instrument level there is a distinction between parameters and variables. Parameters are inputs to the instrument that can be changed at run time, while variables are defined internally within the instrument. This section of the documentation covers these two as they have some similarities." ] }, { "cell_type": "markdown", "id": "strong-muslim", "metadata": {}, "source": [ "## Parameters\n", "Instrument parameters are built on the libpyvinyl parameters, and have some interesting features. First a simple parameter is added." ] }, { "cell_type": "code", "execution_count": 1, "id": "acceptable-emperor", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parameter named: 'first_par' without set value.\n", " [dimensionless]\n", " \n", "\n" ] } ], "source": [ "import mcstasscript as ms\n", "instrument = ms.McStas_instr(\"parameters_and_variables\")\n", "\n", "first_par = instrument.add_parameter(\"first_par\")\n", "print(first_par)" ] }, { "cell_type": "markdown", "id": "alive-cholesterol", "metadata": {}, "source": [ "It is a good habit to add a comment to each parameter when creating it. " ] }, { "cell_type": "code", "execution_count": 2, "id": "adverse-default", "metadata": {}, "outputs": [], "source": [ "second_parameter = instrument.add_parameter(\"second_par\", comment=\"My first parameter!\")" ] }, { "cell_type": "markdown", "id": "downtown-pittsburgh", "metadata": {}, "source": [ "### Types\n", "If only one argument is given, it is assumed the type is a C *double*, so a floating point number. It is also allowed to have integers and strings. No other types are supported by McStas / McXtrace." ] }, { "cell_type": "code", "execution_count": 3, "id": "cellular-server", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " first_par // \n", " second_par // My first parameter!\n", "double double_par // Typed double\n", "int int_par // Typed int\n", "string string_par // Typed string\n" ] } ], "source": [ "double_par = instrument.add_parameter(\"double\", \"double_par\", comment=\"Typed double\")\n", "int_par = instrument.add_parameter(\"int\", \"int_par\", comment=\"Typed int\")\n", "string_par = instrument.add_parameter(\"string\", \"string_par\", comment=\"Typed string\")\n", "\n", "instrument.show_parameters()" ] }, { "cell_type": "markdown", "id": "southern-shoulder", "metadata": {}, "source": [ "### Value\n", "It is common to set the value of a parameter when it is created." ] }, { "cell_type": "code", "execution_count": 4, "id": "rental-indication", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Parameter named: 'par_with_value' with value: 5.2\n", " [dimensionless]\n", " Added value at creation" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "instrument.add_parameter(\"par_with_value\", value=5.2, comment=\"Added value at creation\")" ] }, { "cell_type": "markdown", "id": "expressed-nancy", "metadata": {}, "source": [ "The value can always be changed, either directly or through the instrument object. When using the instrument object, use the name in the instrument file as the keyword argument." ] }, { "cell_type": "code", "execution_count": 5, "id": "narrow-guard", "metadata": {}, "outputs": [], "source": [ "double_par.value = 1.2\n", "instrument.set_parameters(int_par=3)" ] }, { "cell_type": "code", "execution_count": 6, "id": "thirty-sunrise", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " first_par // \n", " second_par // My first parameter!\n", "double double_par = 1.2 // Typed double\n", "int int_par = 3 // Typed int\n", "string string_par // Typed string\n", " par_with_value = 5.2 // Added value at creation\n" ] } ], "source": [ "instrument.show_parameters()" ] }, { "cell_type": "markdown", "id": "cardiac-apparel", "metadata": {}, "source": [ "### Parameter restrictions\n", "Since the parameter object in McStasScript is derived from libpyvinyl, some functionality is inherited in terms of setting parameter restrictions. This comes in the forms of intervals and options, which can both be legal and illegal.\n", "\n", "Here is an example of adding legal intervals to the *double_par* parameter. None can be used if the interval should extend to infinity in the given direction." ] }, { "cell_type": "code", "execution_count": 7, "id": "portuguese-circuit", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parameter named: 'double_par' with value: 1.2\n", " [dimensionless]\n", " Typed double\n", " Legal intervals:\n", " [0,5]\n", " [7,inf]\n", "\n" ] } ], "source": [ "double_par.add_interval(0, 5, intervals_are_legal=True)\n", "double_par.add_interval(7, None, intervals_are_legal=True)\n", "print(double_par)" ] }, { "cell_type": "markdown", "id": "virtual-judges", "metadata": {}, "source": [ "Now only values between 0 and 5 or from 7 to 8 are accepted. Trying to set a different value will raise a ValueError." ] }, { "cell_type": "code", "execution_count": 8, "id": "unknown-edition", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parameter named: 'double_par' with value: 1.8\n", " [dimensionless]\n", " Typed double\n", " Legal intervals:\n", " [0,5]\n", " [7,inf]\n", "\n" ] } ], "source": [ "double_par.value = 1.8\n", "print(double_par)" ] }, { "cell_type": "code", "execution_count": 9, "id": "familiar-church", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parameter named: 'double_par' with value: 10\n", " [dimensionless]\n", " Typed double\n", " Legal intervals:\n", " [0,5]\n", " [7,inf]\n", "\n" ] } ], "source": [ "try:\n", " double_par.value = 10\n", "except:\n", " print(\"Failed to set value!\")\n", " \n", "print(double_par)" ] }, { "cell_type": "markdown", "id": "psychological-voluntary", "metadata": {}, "source": [ "Setting *intervals_are_legal* to False means that only values outside the defined intervals are allowed.\n", "\n", "Options work in a similar way, but for specific values." ] }, { "cell_type": "code", "execution_count": 10, "id": "honey-theta", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Failed to set value!\n", "Parameter named: 'int_par' with value: 3\n", " [dimensionless]\n", " Typed int\n", " Allowed values:\n", " 3\n", " 2\n", " 1\n", "\n" ] } ], "source": [ "int_par.add_option(3, options_are_legal=True)\n", "int_par.add_option(2, options_are_legal=True)\n", "int_par.add_option(1, options_are_legal=True)\n", "\n", "try:\n", " int_par.value = 10\n", "except:\n", " print(\"Failed to set value!\")\n", " \n", "print(int_par)" ] }, { "cell_type": "markdown", "id": "worse-square", "metadata": {}, "source": [ "Adding restrictions to parameters is a healthy habit that can make the produced instrument more resilient to errors. Ensure the given wavelength is a positive number to catch errors early instead of trying to understand what happened when a simulation fails." ] }, { "cell_type": "markdown", "id": "spread-parade", "metadata": {}, "source": [ "## Declared variables\n", "It is possible to declare variables that are used internally in the instrument and as such not exposed to the user. This is done through the instrument objects *add_declare_var* method. It returns a [DeclareVariable](../_autosummary/mcstasscript.helper.mcstas_objects.DeclareVariable.rst) object that can be used to refer to this variable." ] }, { "cell_type": "code", "execution_count": 11, "id": "confidential-village", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Declare variable: 'declared_var' of type double\n" ] } ], "source": [ "declared_var = instrument.add_declare_var(\"double\", \"declared_var\", comment=\"Declared variable\")\n", "print(declared_var)" ] }, { "cell_type": "markdown", "id": "valuable-sigma", "metadata": {}, "source": [ "There are no restrictions on the type for declared variables, typically double and int is used. Declared variables have no methods for additional input, all information must be given at initialization." ] }, { "cell_type": "markdown", "id": "capital-fraction", "metadata": {}, "source": [ "The declared variable can be initialized to a given value by using the *value* keyword." ] }, { "cell_type": "code", "execution_count": 12, "id": "valid-offense", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Declare variable: 'integer' of type int with value: 5\n" ] } ], "source": [ "declared_var = instrument.add_declare_var(\"int\", \"integer\", value=5, comment=\"Declared integer\")\n", "print(declared_var)" ] }, { "cell_type": "markdown", "id": "identified-butter", "metadata": {}, "source": [ "Declared variables can also be one dimensional arrays using the *array* keyword. In the full McStas / McXtrace its possible to make arrays of any dimensionality but only one dimensional is supported in McStasScript. If a value of array is smaller than the length of the given value, the simulation will fail as it would write outside of the declared memory." ] }, { "cell_type": "code", "execution_count": 13, "id": "polish-integration", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Declare variable: 'declared_array' of type double with value: [2, 3, 4]. Array with length 3\n" ] } ], "source": [ "var = instrument.add_declare_var(\"double\", \"declared_array\", value=[2, 3, 4], array=3)\n", "print(var)" ] }, { "cell_type": "markdown", "id": "overall-differential", "metadata": {}, "source": [ "The declared variables of the instrument can be displayed with *show_variables*." ] }, { "cell_type": "code", "execution_count": 14, "id": "after-reply", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "DECLARE VARIABLES \n", "type variable name array length value \n", "-----------------------------------------------\n", "double declared_var \n", "int integer 5 \n", "double declared_array 3 [2, 3, 4] \n", "\n" ] } ], "source": [ "instrument.show_variables()" ] }, { "cell_type": "markdown", "id": "nervous-poverty", "metadata": {}, "source": [ "## User variables\n", "McStas 3.0 introduced USERVARS next to declare variables, these differ in that they are specific to the neutron and can thus be used in EXTEND blocks on McStas 3.0, which is not allowed for normal declare variables. In McStasScript user variables act like declared variables, the only difference being they do not accept a initial value and will show up in a different section of show variables." ] }, { "cell_type": "code", "execution_count": 15, "id": "electronic-police", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Declare variable: 'flag' of type int\n" ] } ], "source": [ "user_var = instrument.add_user_var(\"int\", \"flag\", comment=\"Example of USERVAR\")\n", "print(user_var)" ] }, { "cell_type": "code", "execution_count": 16, "id": "built-folks", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "DECLARE VARIABLES \n", "type variable name array length value \n", "-----------------------------------------------\n", "double declared_var \n", "int integer 5 \n", "double declared_array 3 [2, 3, 4] \n", "\n", "USER VARIABLES (per neutron, only use in EXTEND)\n", "type variable name array length value \n", "-----------------------------------------------\n", "int flag \n", "\n" ] } ], "source": [ "instrument.show_variables()" ] }, { "cell_type": "markdown", "id": "affected-street", "metadata": {}, "source": [ "## Using parameters and variables\n", "Instrument parameters and declare variables are can both be used when setting component attributes. One can use either the name in a string, or the object directly. When using a string, it is allowed to do basic math and use several parameter / variables. It is also possible to select a certain element from an array." ] }, { "cell_type": "code", "execution_count": 17, "id": "dangerous-telling", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "COMPONENT source = Source_simple\n", " \u001b[1myheight\u001b[0m = \u001b[1m\u001b[92minteger\u001b[0m\u001b[0m [m]\n", " \u001b[1mxwidth\u001b[0m = \u001b[1m\u001b[92mdouble_par\u001b[0m\u001b[0m [m]\n", " \u001b[1mdist\u001b[0m = \u001b[1m\u001b[92m5.0*first_par + 0.1*double_par\u001b[0m\u001b[0m [m]\n", " \u001b[1mfocus_xw\u001b[0m = \u001b[1m\u001b[92mdeclared_array[0]\u001b[0m\u001b[0m [m]\n", "AT [0, 0, 0] ABSOLUTE\n" ] } ], "source": [ "source = instrument.add_component(\"source\", \"Source_simple\")\n", "source.xwidth = double_par\n", "source.yheight = declared_var\n", "source.dist = \"5.0*first_par + 0.1*double_par\"\n", "source.focus_xw = \"declared_array[0]\"\n", "print(source)" ] }, { "cell_type": "code", "execution_count": null, "id": "biological-engine", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 5 }