Often described as deformation during which lines remain as lines and parallel lines remain parallel. Homogeneous deformation could be described as affine transformation of initial coordinates
or in matrix form using homogeneous coordinates:
Properties of homogeneous deformation are not spatially dependent
Without translation $\vec{t}$ the homogeneous deformation (rotation and strain) could be described as:
or im matrix form
where $ \mathbf{F} $ is so called deformation gradient.
Note, that as we excluded translation, the origin of coordinates do not change during deformation:
Displacement of particle is vector between initial and final postion, i.e:
or
where $\mathbf{\nabla u}$ is so called displacement gradient.
In [1]:
%pylab inline
Lets try to visualize how unit circle deforms during homogeneous deformation:
In [2]:
# parametric definition of unit circle
theta = linspace(0, 2*pi, 300)
Xc, Yc = cos(theta), sin(theta)
plot(Xc, Yc, 'g')
# Apply deformation gradient and plot ellipse
F = array([[2, 0], [0, 0.5]])
xe, ye = dot(F, [Xc, Yc])
plot(xe, ye, 'r')
axis('equal');
Lets try to visualize how square deforms during homogeneous deformation:
In [3]:
# coordinates of square
Xs = [1, -1, -1, 1, 1]
Ys = [1, 1, -1, -1, 1]
plot(Xs, Ys, 'g')
# Apply deformation gradient and plot result
F = array([[2, 0], [0, 0.5]])
xn, yn = dot(F, [Xs, Ys])
plot(xn, yn, 'r')
axis('equal');
To visualize deformation gradient $\mathbf{F}$ we have to calculate displacement for points on regular grid and plot it using command quiver
.
In [4]:
# create rectangular grid
X, Y = meshgrid(linspace(-2.2, 2.2, 21), linspace(-1.9, 1.9, 17))
# Apply deformation gradient. As [X, Y] is 3D array, we need
# special function to treat dot product properly. tensordot
# can do it.
x, y = tensordot(F, [X, Y], axes=1)
# plot displacement vectors on all point
quiver(X, Y, x-X, y-Y, angles='xy')
plot(Xc, Yc, 'g', xe, ye, 'r')
plot(Xs, Ys, 'g', xn, yn, 'r')
axis('equal');
We can also calculate displacements directly using displacement gradient $\mathbf{\nabla u} = \mathbf{F} - \mathbf{I}$:
In [5]:
# calculate displacements
J = F - eye(2)
u, v = tensordot(J, [X, Y], axes=1)
# plot
quiver(X, Y, u, v, angles='xy')
plot(Xc, Yc, 'g', xe, ye, 'r')
plot(Xs, Ys, 'g', xn, yn, 'r')
axis('equal');
Functions are a convenient way to divide your code into useful blocks, allowing us to order our code, make it more readable, reuse it and save some time. Also functions are a key way to define interfaces so programmers can share their code.
As we have seen already, Python makes use of blocks. A block is a area of code of written in the format of:
block_head:
1st block line
2nd block line
...
Where a block line is more Python code (even another block), and the block head is of the following format: block_keyword block_name(argument1,argument2, ...) Block keywords you already know are "if", "for", and "while".
Functions in python are defined using the block keyword "def", followed with the function's name as the block's name. For example:
In [6]:
def my_function():
print("Hello from my_function!")
Functions may also receive arguments (variables passed from the caller to the function). For example:
In [7]:
def my_function_with_args(username, greeting):
print("Hello {}, I wish you {}".format(username, greeting))
Functions may return a value to the caller, using the keyword- 'return' . For example:
In [8]:
def sum_two_numbers(a, b):
return a + b
In [9]:
# print a simple greeting
my_function()
#prints - "Hello Johny, I wish you a great day!"
my_function_with_args("Johny", "a great day!")
# after this line x will hold the value 7!
x = sum_two_numbers(4, 3)
print(x)
In [10]:
from pylab import *
from scipy import linalg as la
def def_ellipse(F):
# Draw strain ellipse from deformation gradient
theta = linspace(0, 2*pi, 180)
xc, yc = cos(theta), sin(theta)
x,y = dot(F, [xc,yc])
plot(xc, yc, 'r', x, y, 'g')
u, s, v = svd(F)
plot(x, y, 'k', lw=2)
quiver(zeros(2), zeros(2),
hstack((s*u[0],-s*u[0])), hstack((s*u[1],-s*u[1])),
scale=1, units='xy')
axis('equal')
def dis_ellipse(J):
# Draw strain ellipse from displacement gradient
J = asarray(J)
F = J + eye(2)
def_ellipse(F)
def dis_field(J):
# Visualize displacement field from
# displacement gradient
X, Y = meshgrid(linspace(-3, 3, 21),
linspace(-2, 2, 17))
u, v = tensordot(J, [X, Y], axes=1)
quiver(X, Y, u, v, angles='xy')
axis('equal')
def def_field(F):
# Visualize displacement field from
# deformation gradient
F = asarray(F)
J = F - eye(2)
dis_field(J)
def dis_show(J):
# Draw displacement field and deformation ellipse
# from displacement gradient
dis_field(J)
dis_ellipse(J)
show()
def def_show(F):
# Draw displacement field and deformation ellipse
# from deformation gradient
def_field(F)
def_ellipse(F)
show()
To use defined function we simply define deformation or displacement gradient and call appropriate functions:
In [11]:
# Deformation gradient
F = array([[0.5, 1],
[0 , 2]])
def_field(F)
def_ellipse(F)
In [12]:
# Displacement gradient
J = array([[1, 1],
[0, -0.5]])
dis_field(J)
dis_ellipse(J)
In [13]:
from IPython.core.display import HTML
def css_styling():
styles = open("./css/sg2.css", "r").read()
return HTML(styles)
css_styling()
Out[13]: