{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Region basics\n", "\n", "An object on which finite difference mesh, and accordingly, finite difference field are based is `Region`. In this tutorial, we show how to define a region as well as some basic operations.\n", "\n", "A region is can be defined in any number of spatial dimensions. It is always cuboidal and it can be defined by any two diagonally opposite corner points. For instance, let us assume we have a region in 3D Cartesian coordinates with edge lengths:\n", "\n", "$$l_{x} = 100 \\,\\text{nm}$$\n", "$$l_{y} = 50 \\,\\text{nm}$$\n", "$$l_{z} = 20 \\,\\text{nm}$$\n", "\n", "In order to define this region we need to choose two diagonally opposite corner points. There are many possibilities, but it is up to us which corner points we are going to choose as well as where we are going to position our region in Cartesian coordinate system. Most often, we choose either:\n", "\n", "$$p_{1} = (0, 0, 0)$$\n", "$$p_{2} = (l_{x}, l_{y}, l_{z})$$\n", "\n", "or\n", "\n", "$$p_{1} = \\left(-\\frac{l_{x}}{2}, -\\frac{l_{y}}{2}, -\\frac{l_{z}}{2}\\right)$$\n", "$$p_{2} = \\left(\\frac{l_{x}}{2}, \\frac{l_{y}}{2}, \\frac{l_{z}}{2}\\right)$$\n", "\n", "For simplicity, we are going to position $p_{1}$ at the origin of the coordinate system.\n", "\n", "For the three-dimensional Cartesian coordinates, we define points as length-3 tuples and pass them to `Region` object via `p1` and `p2` arguments." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import discretisedfield as df # df is here chosen to be an alias for discretisedfield\n", "\n", "p1 = (0, 0, 0)\n", "p2 = (100e-9, 50e-9, 20e-9)\n", "\n", "region = df.Region(p1=p1, p2=p2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(All units are SI and no prefixes are assumed. Therefore $1 \\,\\text{nm}$ is `1e-9`.)\n", "\n", "The region is now defined. Now, we are going to have a look at some basic methods (functions) which are part of the `Region` object.\n", "\n", "We can ask the region to give us the minimum and maximum points in the region." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0., 0., 0.])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region.pmin" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1.e-07, 5.e-08, 2.e-08])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region.pmax" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also ask the region for its dimensionality using attribute `ndim`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region.ndim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the above example $p_\\text{min} = p_{1}$ and $p_\\text{max} = p_{2}$, however, this is not the case every time. In general one could have chosen any two diagonally opposite points for $p_{1}$ and $p_{2}$ to define the region, for example, ${p}_{1} = (100\\text{e}^{-9}, 0, 0)$ and ${p}_{1} = (0, 50\\text{e}^{-9}, 20\\text{e}^{-9})$ .\n", "\n", "Now we can ask the region to give us the edge lengths of the region (based on $p_{1}$ and $p_{2}$ we used at the definition)." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1.e-07, 5.e-08, 2.e-08])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region.edges" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These lengths correspond to $l_{x}$, $l_{y}$, and $l_{z}$ we discussed earlier.\n", "\n", "Similarly, we can ask for a centre point in the region (cross section point of all diagonals)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([5.0e-08, 2.5e-08, 1.0e-08])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region.center" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Obviously, centre point we got is:\n", "\n", "$$p_\\text{c} = (\\frac{l_{x}}{2}, \\frac{l_{y}}{2}, \\frac{l_{z}}{2})$$\n", "\n", "The volume of the region is:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9.999999999999998e-23" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region.volume" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This value is in $\\text{m}^{3}$ and it is calculated as\n", "\n", "$$V=l_{x}l_{y}l_{z}$$\n", "\n", "Now, let us say we have a point $p$ and want to check if that point is in our region. We can do that using `in`. For instance, if our point is $p = (2\\,\\text{nm}, 4\\,\\text{nm}, 1\\,\\text{nm})$, we can ask the region if point $p$ is in it." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p = (2e-9, 4e-9, 1e-9)\n", "\n", "p in region" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a result, we get `bool` (either `True` or `False`). This can be useful, when we want to use these expressions as conditions for some more complex functions. For example:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Point: I'm in! :)\n" ] } ], "source": [ "if p in region:\n", " print(\"Point: I'm in! :)\")\n", "else:\n", " print(\"Point: I'm out! :(\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the other hand, we could have chosen a point which is outside of our region:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(1e-9, 200e-9, 0) in region" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sometimes we want to check if two regions are the same. We can do that using relational `==` operator. Let us define two regions: one which is the same to the one we have and one different:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "region_same = df.Region(p1=(0, 0, 0), p2=(100e-9, 50e-9, 20e-9))\n", "region_different = df.Region(p1=(0, 0, 0), p2=(10e-9, 5e-9, 2e-9))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can compare them:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region == region_same" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region == region_different" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just like `in` operator, `==` returns `bool`. Similarly, we can ask if two regions are different:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region != region_same" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "region != region_different" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can ask the region object about its representation string:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\"Region(pmin=[0.0, 0.0, 0.0], pmax=[1e-07, 5e-08, 2e-08], dims=['x', 'y', 'z'], units=['m', 'm', 'm'])\"" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "repr(region)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In a Jupyter notebook we can also get an HTML representation." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "Region\n", "