2022-04-07 18:46:57 +02:00

383 lines
10 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Description\n",
"\n",
"This notebook intends to gather all the functionalities you'll have to implement for assignment 2.1. You will have to generate an elastic solid, deform it, compute the associated Jacobian of the deformation map $\\phi$, and implement pinning constraints. You will also visualize the eigenvectors and eigenvalues of the metric tensor, given a prescribed deformation.\n",
"\n",
"# Load libraries"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import igl\n",
"import meshplot as mp\n",
"\n",
"import sys as _sys\n",
"_sys.path.append(\"../src\")\n",
"from elasticsolid import *\n",
"from eigendecomposition_metric import *\n",
"\n",
"shadingOptions = {\n",
" \"flat\":True,\n",
" \"wireframe\":False, \n",
"}\n",
"\n",
"rot = np.array(\n",
" [[1, 0, 0 ],\n",
" [0, 0, 1],\n",
" [0, -1, 0 ]]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Load mesh\n",
"\n",
"Several meshes are available for you to play with under `data/`: `ball.obj`, `dinosaur.obj`, and `beam.obj`. You can also uncomment the few commented lines below to manipulate a simple mesh made out of 2 tetrahedra."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "33e8252ccc4d4c9298094b0dc3675ee4",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"v, _, _, t, _, _ = igl.read_obj(\"../data/dinosaur.obj\")\n",
"\n",
"# t = np.array([\n",
"# [0, 1, 2, 3],\n",
"# [1, 2, 3, 4]\n",
"# ])\n",
"# v = np.array([\n",
"# [0., 0., 0.],\n",
"# [1., 0., 0.],\n",
"# [0., 1., 0.],\n",
"# [0., 0., 1.],\n",
"# [2/3, 2/3, 2/3]\n",
"# ])\n",
"\n",
"aabb = np.max(v, axis=0) - np.min(v, axis=0)\n",
"length_scale = np.mean(aabb)\n",
"\n",
"p = mp.plot(v @ rot.T, t, shading=shadingOptions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Manipulate elastic solids\n",
"\n",
"## Instanciation\n",
"\n",
"The rest shape matrices $D_m$ and their inverse matrices $B_m$ are computed during instanciation."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"rho = 131 # [kg.m-3]\n",
"solid = ElasticSolid(v, t, rho=rho)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Deform the mesh\n",
"\n",
"This part involves Jacobian computation which relies on deformed shape matrices $D_s$."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "02c94de8642645d8aab800877f8ddbce",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"<meshplot.Viewer.Viewer at 0x7fa7dc789070>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v_def = v.copy()\n",
"v_def[:, 2] *= 2.\n",
"solid.update_def_shape(v_def)\n",
"\n",
"mp.plot(solid.v_def @ rot.T, solid.t, shading=shadingOptions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Visualize some properties of the metric tensor\n",
"\n",
"The metric tensor measures how stretched and sheared directions in the undeformed space are under the deformation $\\phi$. It is defined from the Jacobian of the deformation $\\mathbf{F}$ as follow (see the handout for a derivation):\n",
"\n",
"$$\\mathbf{M} = \\mathbf{F}^T \\mathbf{F}$$\n",
"\n",
"We intend to plot the eigenvectors coloured by the corresponding eigenvalues in the next cell."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6ff42798692c4a29ad4a37f40ca77a84",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# We limit ourselves to stretching the mesh in the z direction\n",
"# Feel free to experiment with other kinds of deformations!\n",
"\n",
"v_def = v.copy()\n",
"v_def[:, 2] *= 2.0\n",
"solid.update_def_shape(v_def)\n",
"\n",
"squared_eigvals, eigvecs = compute_eigendecomposition_metric(solid.F)\n",
"plot_eigendecomposition_metric(solid, squared_eigvals, eigvecs, rot, scale=0.05)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pin vertices of the mesh\n",
"\n",
"Pass a `pin_idx` to the constructor, compute the mask for deformations."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"maxZ = np.max(solid.v_rest[:, 2])\n",
"pin_idx = np.arange(solid.v_rest.shape[0])[solid.v_rest[:, 2] > maxZ - 0.1 * aabb[2]]\n",
"\n",
"v_def = v.copy()\n",
"v_def[:, 2] -= 0.1 * aabb[2]\n",
"solid.update_def_shape(v_def)\n",
"\n",
"solid_pinned = ElasticSolid(v, t, rho=rho, pin_idx=pin_idx)\n",
"solid_pinned.update_def_shape(v_def)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "13f958a33ec945ca979aca15d7381e01",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"p = mp.plot(solid_pinned.v_def @ rot.T, t, shading=shadingOptions)\n",
"p.add_points(solid_pinned.v_def[pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2.4 Derivation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Volume of tetrahedron ($X_1, X_2, X_3, X_4$) is given by $\\frac{1}{6}|det(D_m)|$\n",
"\n",
"We can decompose the provided formula:\n",
"\n",
"$Vol = \\frac{1}{6}|det(D_m)| = \\frac{1}{6}|D_{m1}^T \\cdot (D_{m2} \\times D_{m3})|$\n",
"\n",
"\n",
"Next, we build 3 vectors:\n",
"\n",
"$V_0 = X_1 - X_4 = \\begin{pmatrix}X_{x1}-X_{x4} \\\\ Y_{x1}-Y_{x4} \\\\ Z_{x1}- Z_{x4} \\end{pmatrix}$\n",
"\n",
"$V_1 = X_2 - X_4 = \\begin{pmatrix}X_{x2}-X_{x4} \\\\ Y_{x2}-Y_{x4} \\\\ Z_{x2}- Z_{x4} \\end{pmatrix}$\n",
"\n",
"$V_2 = X_3 - X_4 = \\begin{pmatrix}X_{x3}-X_{x4} \\\\ Y_{x3}-Y_{x4} \\\\ Z_{x3}- Z_{x4} \\end{pmatrix}$\n",
"\n",
"We then compute the base as:\n",
"\n",
"$B = V_1 \\times V_2$\n",
"\n",
"And also the height as:\n",
"\n",
"$H = V_0$\n",
"\n",
"From this we can compute the volume:\n",
"\n",
"$Vol = \\frac{1}{6} \\cdot B \\cdot H = \\frac{1}{6} V_0 \\cdot (V_1 \\times V_2)$\n",
"\n",
"We can note the similarity between both fomulas. We can note the equality between both formulas: \n",
"\n",
"$V_0 = D_{m1}, V_1 = D_{m2}, V_2 = D_{m3}$\n",
"\n",
"Note that the absolute value is not directly taken into account since its absolute volume and not signed volume.\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2.7 Derivation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show that: $Vol(x_1, x_2, x_3, x_4)/Vol(X_1, X_2, X_3, X_4) = |det(F)|$\n",
"\n",
"Since we know that $F = D_s D_m^{-1}$, and that: $V = \\frac{1}{6}|det(D_m)|$\n",
"\n",
"We can drag the det and abs into it:\n",
"\n",
"$|det(F)| = \\frac{|det(D_s)|}{|det(D_m)|} = \\frac{\\frac{1}{6}|det(D_s)|}{\\frac{1}{6}|det(D_m)|} = \\frac{Vol(x_1, x_2, x_3, x_4)}{Vol(X_1, X_2, X_3, X_4)}$\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}