{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# `Parameter` descriptor\n", "\n", "In various simulations, it is necessary to have the possibility to define a parameter in several different ways. The most common case is to define a different value of a parameter in different regions of the mesh. This can be, for example, achieved by passing a dictionary, whose keys are the names of regions (strings), and values are the values of the parameter. On the other hand, if the parameter is not spatially varying, it is common to provide a single value.\n", "\n", "Let us say we have a temperature parameter. We can pass the temperature as a single value for all discretisation cells (`T = 300`) or as a dictionary (`T = {'region1': 250, 'region2': 300}`) defining the temperature in different regions. Accordingly, we need a descriptor which would be able to accept both values. More precisely, the passed value has to satisy the following checks:\n", "\n", "1. If the value is not a dictionary, does it satisfy the rules of a descriptor passed as `descriptor` argument.\n", "2. If the value is a dictionary, are all its keys valid Python variable names (`ubermagutil.typesystem.Name`) and all its values satisfy the rules of a descriptor passed as `descriptor` argument.\n", "\n", "Let us now impose the typesystem using `ubermagutil.typesystem.Parameter` descriptor." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import ubermagutil.typesystem as ts\n", "\n", "\n", "@ts.typesystem(T=ts.Parameter(descriptor=ts.Scalar()))\n", "class Weather:\n", " def __init__(self, T):\n", " self.T = T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now instantiate the class and set `T` attribute." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "300" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w = Weather(T=300)\n", "w.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also change its value to be a dictionary." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'region1': 250, 'region2': 300}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w.T = {\"region1\": 250, \"region2\": 300}\n", "w.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, if we attempt to pass a tuple, an exception is raised:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception raised.\n" ] } ], "source": [ "try:\n", " w.T = (250, 300)\n", "except TypeError:\n", " print(\"Exception raised.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An exception will also be raised if we attempt to pass an empty dictionary:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception raised.\n" ] } ], "source": [ "try:\n", " w.T = {}\n", "except ValueError:\n", " print(\"Exception raised.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, if the dictionary is not well defined, the value is rejected." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception raised.\n" ] } ], "source": [ "try:\n", " w.T = {\"region1\": 250, \"region2\": (300, 200)}\n", "except TypeError:\n", " print(\"Exception raised.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`ValueError` would also be raised if one of the keys of the dictionary is not a valid Python variable name." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception raised.\n" ] } ], "source": [ "try:\n", " w.T = {\"region1\": 250, \"region 2\": (300, 200)}\n", "except ValueError:\n", " print(\"Exception raised.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similar to other descriptors, we can also pass `const=True` to forbid changing the value of the attribute." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "300" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@ts.typesystem(T=ts.Parameter(descriptor=ts.Scalar(), const=True))\n", "class Weather:\n", " def __init__(self, T):\n", " self.T = T\n", "\n", "\n", "w = Weather(T=300)\n", "w.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we try to change its value:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception raised.\n" ] } ], "source": [ "try:\n", " w.T = 250\n", "except AttributeError:\n", " print(\"Exception raised.\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.9" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }