Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "from numpy import *\n",
- "from numpy.linalg import inv, norm, det\n",
- "from scipy.linalg import sqrtm"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# The Polar Decomposition\n",
- "\n",
- "The polar decomposition, derivable from the singular value decomposition, states that the deformation gradient $F_{iJ}$ can be factorized as\n",
- "\n",
- "$$ F_{iJ} = R_{iK}U_{KJ} $$\n",
- "\n",
- "where $R_{iK}$ is unitary and $U_{KJ}$ symmetric-positive-definite.\n",
- "\n",
- "Left multiplying both sides by $F_{iL}$ gives\n",
- "\n",
- "$$ \\begin{align}\n",
- " F_{iL} F_{iJ} &= F_{iL} R_{iK}U_{KJ} \\\\\n",
- " &= R_{iM}U_{ML} R_{iK}U_{KJ} \\\\\n",
- " &= U_{ML} R_{iM}R_{iK} U_{KJ} \\\\\n",
- " &= U_{ML} \\delta_{MK} U_{KJ} \\\\\n",
- " &= U_{ML} U_{MJ} \\\\\n",
- " &= U_{LM} U_{MJ}\n",
- "\\end{align} $$\n",
- "\n",
- "In direct the notation:\n",
- "\n",
- "$$ \\boldsymbol{F}^{\\mathrm{T}}{\\cdot}\\boldsymbol{F} =\n",
- " \\boldsymbol{U}{\\cdot}\\boldsymbol{U} $$\n",
- "\n",
- "Analytically, the polar decomposition can be found from\n",
- "\n",
- "- Step 1\n",
- "\n",
- " $$\\boldsymbol{U} = \\left[\n",
- " \\boldsymbol{F}^{\\mathrm{T}}{\\cdot}\\boldsymbol{F}\n",
- " \\right]^{1/2}$$\n",
- " \n",
- "- Step 2\n",
- "\n",
- " $$\\boldsymbol{R} = \\boldsymbol{F}{\\cdot}\\boldsymbol{U}^{-1}$$\n",
- " \n",
- "A few red flags should be raised when viewing the preceding algorithm:\n",
- "\n",
- "- In Step 1, the matrix square root is taken. This is an expensive calculation in its own right. Often requiring an eigen analysis.\n",
- "\n",
- "- In Step 2, the matrix inverse is taken. For symmetric-positive-definite matrices (like $\\boldsymbol{U}$), there exist efficient procedures to determine the inverse. But, it's best to use algorithms that do not require it."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Iterative Polar Decomposition\n",
- "\n",
- "The Taylor series expansion of $\\left(\\boldsymbol{I}-\\boldsymbol{X}\\right)^n$, where $\\boldsymbol{X}$ is a symmetric second-order tensor, is\n",
- "\n",
- "$$\n",
- "\\left(\\boldsymbol{I}-\\boldsymbol{X}\\right)^n \\approx\n",
- " \\boldsymbol{I} - n\\boldsymbol{X} + \n",
- " \\mathcal{O}\\left(\\boldsymbol{X}^2\\right)\n",
- "$$\n",
- "\n",
- "Let $\\boldsymbol{X} = \\boldsymbol{I} - \\boldsymbol{A}$, then\n",
- "\n",
- "$$\n",
- "\\boldsymbol{A}^n \\approx\n",
- " \\boldsymbol{I} - n\\left(\\boldsymbol{I} - \\boldsymbol{X}\\right) + \n",
- " \\mathcal{O}\\left(\\left(\\boldsymbol{I} - \\boldsymbol{X}\\right)^2\\right)\n",
- "$$\n",
- "\n",
- "For $n=-1/2$,\n",
- "\n",
- "$$\n",
- "\\boldsymbol{A}^{-1/2} \\approx\n",
- " \\boldsymbol{I} + \\frac{1}{2}\\left(\n",
- " \\boldsymbol{I} - \\boldsymbol{X}\n",
- " \\right) + \n",
- " \\mathcal{O}\\left(\\left(\\boldsymbol{I} - \\boldsymbol{X}\\right)^2\\right)\n",
- "$$\n",
- "\n",
- "Recall that \n",
- "\n",
- "$$\\boldsymbol{F} = \\boldsymbol{R}{\\cdot}\\boldsymbol{U}$$\n",
- "\n",
- "Let \n",
- "\n",
- "$$\n",
- " \\boldsymbol{C} = \n",
- " \\boldsymbol{F}^T{\\cdot}\\boldsymbol{F} = \n",
- " \\boldsymbol{U}^2 \\Rightarrow\n",
- " \\boldsymbol{U}^{-1} =\n",
- " \\left(\\boldsymbol{F}^T{\\cdot}\\boldsymbol{F}\\right)^{-1/2}\n",
- "$$\n",
- "\n",
- "So,\n",
- "\n",
- "$$\n",
- " \\boldsymbol{R} = \n",
- " \\boldsymbol{F}{\\cdot}\\boldsymbol{U}^{-1} = \n",
- " \\boldsymbol{F}{\\cdot}\\boldsymbol{C}^{-1/2}\n",
- "$$\n",
- "\n",
- "If the eigenvalues of $\\boldsymbol{U}$ are close to $1$, the Taylor series expansion is \n",
- "\n",
- "$$\n",
- " \\boldsymbol{C}^{-1/2} = \n",
- " \\boldsymbol{I} + \\frac{1}{2}\\left(\\boldsymbol{I} - \\boldsymbol{C}\\right) =\n",
- " \\boldsymbol{I} + \\frac{1}{2}\\left(\\boldsymbol{I} - \\boldsymbol{F}^T{\\cdot}\\boldsymbol{F}\\right) =\n",
- " \\frac{3}{2}\\boldsymbol{I} - \\frac{1}{2}\\boldsymbol{F}^T{\\cdot}\\boldsymbol{F}\n",
- "$$\n",
- "\n",
- "So,\n",
- "\n",
- "$$\n",
- "\\boldsymbol{R} = \\frac{1}{2}\\boldsymbol{F}\\left(\n",
- " 3\\boldsymbol{I} - \\boldsymbol{F}^T{\\cdot}\\boldsymbol{F}\n",
- " \\right)\n",
- "$$\n",
- "\n",
- "Using fixed point iterations, $\\boldsymbol{R}$ can then be refined by\n",
- "\n",
- "$$\n",
- "\\boldsymbol{R}_{n+1} = \\frac{1}{2}\\boldsymbol{R}_n\\left(\n",
- " 3\\boldsymbol{I} - \\boldsymbol{R}^T_n{\\cdot}\\boldsymbol{R}_n\n",
- " \\right)\n",
- "$$\n",
- "\n",
- "$\\boldsymbol{R}_0$ can be chosen as $\\boldsymbol{F}$."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Function Definitions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Analytic Polar Decomposition"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "def AnalyticPolarDecomposition(F):\n",
- " U = sqrtm(dot(F.T, F))\n",
- " R = dot(F, inv(U))\n",
- " return R, U"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Numeric Polar Decomposition"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "def NumericPolarDecomposition(F, niter=20, tol=1e-8, disp=0):\n",
- " I = eye(3)\n",
- " R = F\n",
- " absmax = lambda x: amax(abs(x))\n",
- " for i in range(niter):\n",
- " R = .5 * dot(R, 3 * I - dot(R.T, R))\n",
- " if absmax(dot(R.T, R) - I) < tol:\n",
- " break\n",
- " else:\n",
- " raise RuntimeError('Fast polar decompositon failed to converge')\n",
- " U = dot(R.T, F)\n",
- " if disp:\n",
- " print 'Fast polar decomposition converged ',\n",
- " print 'in {0} iterations'.format(i)\n",
- " return R, U"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Evaluation"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "# Define the deformation gradient\n",
- "F = array([[1, .5, 0], [0, 1, 0], [0, 0, 1.5]])\n",
- "assert det(F) > 0\n",
- "F"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "# Verify\n",
- "Ra, Ua = AnalyticPolarDecomposition(F)\n",
- "Ri, Ui = NumericPolarDecomposition(F, tol=1e-5, disp=1)\n",
- "assert allclose(Ra, Ri)\n",
- "assert allclose(Ua, Ui)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "%%timeit\n",
- "R, U = AnalyticPolarDecomposition(F)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "%%timeit\n",
- "R, U = NumericPolarDecomposition(F, tol=1e-5)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 2",
- "language": "python",
- "name": "python2"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 2
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython2",
- "version": "2.7.10"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement