{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# The structure of a mesh" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "To explain the structure of a mesh, we create a helper function:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from sigmaepsilon.mesh import PointData, PolyData\n", "from sigmaepsilon.mesh.cells import T3, Q4, L2\n", "import numpy as np\n", "\n", "\n", "def generate_mesh(to_standard_form:bool=False):\n", "\n", " coords_T3 = np.array([\n", " [0, 0, 0],\n", " [1, 0, 0],\n", " [1, 1, 0],\n", " [0, 1, 0],\n", " ], dtype=float)\n", "\n", " topology_T3 = np.array([\n", " [0, 1, 2],\n", " [0, 2, 3],\n", " ], dtype=int)\n", "\n", " coords_Q4 = np.array([\n", " [2, 0, 0],\n", " [3, 0, 0],\n", " [3, 1, 0],\n", " [2, 1, 0],\n", " ], dtype=float)\n", "\n", " topology_Q4 = np.array([\n", " [0, 1, 2, 3],\n", " ], dtype=int)\n", "\n", " coords_L2 = np.array([\n", " [1, 0, 0],\n", " [2, 1, 0],\n", " [1, 1, 0],\n", " [2, 0, 0],\n", " ], dtype=float)\n", "\n", " topology_L2 = np.array([\n", " [0, 1],\n", " [2, 3]\n", " ], dtype=int)\n", "\n", " pd_T3 = PointData(coords=coords_T3)\n", " cd_T3 = T3(topo=topology_T3)\n", "\n", " pd_Q4 = PointData(coords=coords_Q4)\n", " cd_Q4 = Q4(topo=topology_Q4)\n", "\n", " pd_L2 = PointData(coords=coords_L2)\n", " cd_L2 = L2(topo=topology_L2)\n", "\n", " mesh = PolyData()\n", " mesh[\"2d\", \"triangles\"] = PolyData(pd_T3, cd_T3)\n", " mesh[\"2d\", \"quads\"] = PolyData(pd_Q4, cd_Q4)\n", " mesh[\"lines\"] = PolyData(pd_L2, cd_L2)\n", " \n", " if to_standard_form:\n", " mesh.to_standard_form()\n", " \n", " return mesh\n", "\n", "\n", "mesh = generate_mesh()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## The database model" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "A ``PolyData`` object is essentially a dictionary, equipped with one or two Awkward arrays to store data attached to the points and the cells. Instances walk and talk like a dictionary but the behaviour is extended to cover nested definitions." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(mesh, dict)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['2d', 'lines']" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(mesh.keys())" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[PolyData({'triangles': PolyData({}), 'quads': PolyData({})}), PolyData({})]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(mesh.values())" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, the `values` call returns only two items, but the mesh has three blocks. To loop through the subdictionaries (called blocks) with cell data, you can use the ``cellblocks`` method of any ``PolyData`` instance. Every block has an address and a parent except the root object, that has no parent and address." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['2d', 'triangles']\n", "['2d', 'quads']\n", "['lines']\n" ] } ], "source": [ "for block in mesh.cellblocks(inclusive=True):\n", " print(block.address)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The parameter ``inclusive`` means to start parsing the structure of the mesh with the instance the call was made upon. In this case it makes no difference, as the root instance of the mesh has no attached cells." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['2d', 'triangles']\n", "['2d', 'quads']\n", "['lines']\n" ] } ], "source": [ "for block in mesh.pointblocks(inclusive=True):\n", " print(block.address)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Now bring the mesh into a standard form and repeat the above queries:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PolyData({'2d': PolyData({'triangles': PolyData({}), 'quads': PolyData({})}), 'lines': PolyData({})})" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mesh.to_standard_form()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['2d', 'triangles']\n", "['2d', 'quads']\n", "['lines']\n" ] } ], "source": [ "for block in mesh.cellblocks(inclusive=True):\n", " print(block.address)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[]\n" ] } ], "source": [ "for block in mesh.pointblocks(inclusive=True):\n", " print(block.address)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "An empty list is returned, since the root of the mesh does host a point cloud, but it doesn't have an address. To see if a block has an attached point or cell related data,use the `pointdata` and `celldata` properties (you can also use `mesh.pd` and `mesh.cd`):" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "mesh = generate_mesh()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
[{_x: [0, 0, 0], _activity: True, _id: 0},\n",
" {_x: [1, 0, 0], _activity: True, _id: 1},\n",
" {_x: [1, 1, 0], _activity: True, _id: 2},\n",
" {_x: [0, 1, 0], _activity: True, _id: 3}]\n",
"------------------------------------------\n",
"type: 4 * {\n",
" _x: 3 * float64,\n",
" _activity: bool,\n",
" _id: int32\n",
"}"
],
"text/plain": [
"[{_nodes: [0, 1, 2], _id: 0},\n",
" {_nodes: [0, 2, 3], _id: 1}]\n",
"-----------------------------\n",
"type: 2 * {\n",
" _nodes: 3 * int32,\n",
" _id: int32\n",
"}"
],
"text/plain": [
"[{_nodes: [0, 1, 2], _id: 0},\n",
" {_nodes: [0, 2, 3], _id: 1}]\n",
"-----------------------------\n",
"type: 2 * {\n",
" _nodes: 3 * int32,\n",
" _id: int32\n",
"}"
],
"text/plain": [
"[{_nodes: [0, 1, 2], _id: 0, random_data: 0.479},\n",
" {_nodes: [0, 2, 3], _id: 1, random_data: 0.56}]\n",
"-------------------------------------------------\n",
"type: 2 * {\n",
" _nodes: 3 * int32,\n",
" _id: int32,\n",
" random_data: float64\n",
"}"
],
"text/plain": [
"[0.479,\n",
" 0.56]\n",
"-----------------\n",
"type: 2 * float64"
],
"text/plain": [
"[0.479,\n",
" 0.56]\n",
"-----------------\n",
"type: 2 * float64"
],
"text/plain": [
"[{random_data: 0.931, _activity: True, _id: 0, _x: [0, ..., 0]},\n",
" {random_data: 0.981, _activity: True, _id: 1, _x: [1, ..., 0]},\n",
" {random_data: 0.234, _activity: True, _id: 2, _x: [1, ..., 0]},\n",
" {random_data: 0.589, _activity: True, _id: 3, _x: [0, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 4, _x: [2, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 5, _x: [3, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 6, _x: [3, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 7, _x: [2, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 8, _x: [1, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 9, _x: [2, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 10, _x: [1, ..., 0]},\n",
" {random_data: nan, _activity: True, _id: 11, _x: [2, ..., 0]}]\n",
"----------------------------------------------------------------\n",
"type: 12 * {\n",
" random_data: float64,\n",
" _activity: bool,\n",
" _id: int32,\n",
" _x: 3 * float64\n",
"}"
],
"text/plain": [
"| \n", " | random_data | \n", "
|---|---|
| entry | \n", "\n", " |
| 0 | \n", "0.930941 | \n", "
| 1 | \n", "0.980779 | \n", "
| 2 | \n", "0.234165 | \n", "
| 3 | \n", "0.589487 | \n", "
| 4 | \n", "NaN | \n", "
| 5 | \n", "NaN | \n", "
| 6 | \n", "NaN | \n", "
| 7 | \n", "NaN | \n", "
| 8 | \n", "NaN | \n", "
| 9 | \n", "NaN | \n", "
| 10 | \n", "NaN | \n", "
| 11 | \n", "NaN | \n", "