Files
JuliaFEM.jl/notebooks/2015-09-15-2d-segmentation.ipynb
T
2015-09-24 07:57:34 +03:00

550 lines
56 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Contact segmentation in 2d\n",
"\n",
"Author(s): Jukka Aho\n",
"\n",
"**Abstract**: Contact segmentation in 2d"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING: could not import Base.help into PyCall\n"
]
}
],
"source": [
"using JuliaFEM: PSeg, get_field, set_field, interpolate, new_field!, push_field!\n",
"using JuliaFEM: calculate_normals!, average_normals!, fit_derivative_field!\n",
"using JuliaFEM: set_degree, get_number_of_basis_functions, dinterpolate\n",
"using PyPlot\n",
"using ForwardDiff"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create some test boundaries"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"rlinspace (generic function with 1 method)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function rlinspace(X1, X2, R, n, p0)\n",
" fx(ϕ, xc) = R*cos(ϕ) + xc\n",
" fy(ϕ, yc) = R*sin(ϕ) + yc\n",
" function F(p)\n",
" ϕ1, ϕ2, xc, yc = p\n",
" return [\n",
" fx(ϕ1, xc) - X1[1]\n",
" fy(ϕ1, yc) - X1[2]\n",
" fx(ϕ2, xc) - X2[1]\n",
" fy(ϕ2, yc) - X2[2]\n",
" ]\n",
" end\n",
" J = ForwardDiff.jacobian(F)\n",
" p = copy(p0)\n",
" for i=1:10\n",
" dp = -J(p) \\ F(p)\n",
" p += dp\n",
" if norm(dp) < 1.0e-9\n",
" println(\"Converged. p = $p\")\n",
" break\n",
" end\n",
" end\n",
" ϕ1, ϕ2, xc, yc = p\n",
" ϕ = linspace(ϕ2, ϕ1, n)\n",
" return fx(ϕ, xc), fy(ϕ, yc)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Converged. p = [4.2905787641613236,5.624156522861784,0.04706336239279979,6.561746550428803]\n"
]
},
{
"data": {
"image/png": [
"iVBORw0KGgoAAAANSUhEUgAAAzgAAAEeCAYAAABG5rCAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAIABJREFUeJzs3XtcVVX+//HX4X5HRU2JME0wM40k1LCLZt/MBLwEKDOa6ZTNTFdsUrMpv2XONFaj4zg2U7/SQY3xK2kKWpqW5TimJpaVElIhGqCCoSgXuZzfH2egkNsBgQ3nvJ+Px3moa++192fXFnmz1l7bZDabzYiIiIiIiNgAB6MLEBERERERaSkKOCIiIiIiYjMUcERERERExGYo4IiIiIiIiM1QwBEREREREZuhgCMiIiIiIjZDAUdERERERGyGAo6IiIiIiNgMBRwREREREbEZCjgiIiIiImIznJqy89dff83//u//kpqaSm5uLm5ubvTr14+HH36YX/7ylw32XblyJTNmzKhzW25uLt27d6/VnpeXx9atW7n66qtxd3dvSqkiIiIiImJDiouLyczMZPTo0XTt2rXe/ZoUcLKysjh//jz3338//v7+FBUVkZSUxNSpU8nMzOSZZ55p9BgLFiygd+/eNdp8fX3r3Hfr1q1MmTKlKSWKiIiIiIgNW716dYODKyaz2Wy+nBNUVlYSGhrKmTNnOHbsWL37VY3gfPbZZwwePNiqY+/evZtbbrmF1atX079//8sps0OKj49n8eLFRpchBtN9ILoHBHQfiIXuAwH7vQ+OHDnClClT+Pe//83w4cPr3a9JIzh1cXBwICAggMLCQqv2N5vNFBYW4uHhgaOjY4P7Vk1L69+/v9WhyJb4+vra5XVLTboPRPeAgO4DsdB9IKD7oLFHV5q1yEBRURF5eXl8++23LF68mK1btzJ79myr+o4cORJfX188PT0ZN24cGRkZzSlBRERExC4cOXKEoKAgXF1dSUlJwdXVlaCgII4cOWJ0aSLtUrNGcGbNmsXrr79uOYCTE0uXLmXmzJkN9vH09GT69OmMHDkSHx8fPvvsM/785z8THh5OamoqAQEBzSlFRERExGZ9/fXXhISEUF5eXt128eJFMjIyGDRoEIcOHbLLafwiDWlWwImPjyc2Npbs7GzWrFnDI488gru7O9OmTau3T0xMDDExMdV/joqKYvTo0dx2220sXLiQ1157rTmliIiIiNis8ePH1wg3P1deXk5UVBRHjx5t46pE2rdmBZx+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"
],
"text/plain": [
"PyPlot.Figure(PyObject <matplotlib.figure.Figure object at 0x7faeec09ee10>)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(-0.1,3.6)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Converged. p = [2.110067133637596,1.2802355090457196,1.5675520985912952,-3.7904167887303712]\n"
]
}
],
"source": [
"srand(42)\n",
"\n",
"nsl = 6\n",
"nm = 5\n",
"\n",
"ϕ11 = 5.4\n",
"ϕ12 = 4.6\n",
"R1 = 5\n",
"xc1 = -0.8\n",
"yc1 = 9.9\n",
"X1 = [-2.0, 2.0]\n",
"X2 = [4.0, 3.5]\n",
"x1, y1 = rlinspace(X1, X2, R1, nsl, [ϕ11, ϕ12, xc1, yc1])\n",
"\n",
"ϕ11 = 2.2\n",
"ϕ12 = 1.1\n",
"R1 = 5\n",
"xc1 = 1.9\n",
"yc1 = -4.1\n",
"X1 = [-1.0, 0.5]\n",
"X2 = [3.0, 1.0]\n",
"x2, y2 = rlinspace(X1, X2, R1, nsl, [ϕ11, ϕ12, xc1, yc1])\n",
"\n",
"#x1 = linspace(0, 3, nsl) + rand(nsl)*0.1\n",
"#y1 = 0.5*rand(nsl)\n",
"#x2 = linspace(0, 3, nm) + rand(nm)*0.1 + 0.4\n",
"#y2 = 0.5*rand(nm) + 0.5\n",
"\n",
"function create_elements(X, sid=0)\n",
" Γ = []\n",
" nnodes = size(X, 2)\n",
" nelements = nnodes-1\n",
" for i=1:nelements\n",
" con = sid+[i, i+1]\n",
" el = PSeg(con)\n",
" set_field(el, :Geometry, Vector[X[:, i], X[:, i+1]])\n",
" push!(Γ, el)\n",
" end\n",
" return Γ\n",
"end\n",
"Γ₁ = create_elements([x1 y1]', 0)\n",
"Γ₂ = create_elements([x2 y2]', nsl);\n",
"\n",
"# calculate and average normals like se did in last notebook\n",
"for el in [Γ₁; Γ₂]\n",
" calculate_normals!(el)\n",
"end\n",
"average_normals!(Γ₁)\n",
"average_normals!(Γ₂)\n",
"\n",
"function plot_element(el; plot_with_normal=false)\n",
" # create a array of vectors\n",
" xis = Vector[[xi] for xi in linspace(-1, 1)]\n",
" coords = interpolate(el, :Geometry, xis)\n",
" normals = interpolate(el, :Normals, Vector[[-1.0], [1.0]])\n",
" ncoords = interpolate(el, :Geometry, Vector[[-1.0], [1.0]])\n",
" xs = [X[1] for X in coords]\n",
" ys = [X[2] for X in coords]\n",
" plot(xs, ys, \"-\")\n",
" plot([xs[1], xs[end]], [ys[1], ys[end]], \"ko\")\n",
" plot([xs[1], xs[end]], [ys[1], ys[end]], \"ko\")\n",
" if plot_with_normal\n",
" for i=1:2\n",
" p0 = ncoords[i]\n",
" p1 = ncoords[i]+0.3*normals[i]\n",
" plot([p0[1], p1[1]], [p0[2], p1[2]], \"-k\")\n",
" end\n",
" end\n",
"end\n",
"\n",
"\n",
"figure(figsize=(10, 3))\n",
"for el in Γ₁\n",
" plot_element(el; plot_with_normal=true)\n",
"end\n",
"for el in Γ₂\n",
" plot_element(el; plot_with_normal=false)\n",
"end\n",
"axis(\"equal\")\n",
"ylim(-0.1, 3.6)\n",
"#axis(\"off\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"6x2 Array{Float64,2}:\n",
" 4.0 3.5 \n",
" 3.05326 2.5664 \n",
" 1.89394 1.91534\n",
" 0.60401 1.59286\n",
" -0.725305 1.62176\n",
" -2.0 2.0 "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[x1 y1]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"6x2 Array{Float64,2}:\n",
" 3.0 1.0 \n",
" 2.18891 1.17082\n",
" 1.36075 1.2053 \n",
" 0.538273 1.10249\n",
" -0.255919 0.86522\n",
" -1.0 0.5 "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[x2 y2]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"calc_projection (generic function with 1 method)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function newton(R, dR, x0=0.0; max_iterations=10, tol=1.0e-9)\n",
" x = x0\n",
" for i=1:max_iterations\n",
" dx = -R(x)/dR(x)\n",
" x += dx\n",
" if abs(dx) < tol\n",
" break\n",
" end\n",
" end\n",
" x\n",
"end\n",
"\n",
"\"\"\"\n",
"Find projection from slave nodes to master element.\n",
"\n",
"Parameters\n",
"----------\n",
"sel :: Element\n",
" slave element\n",
"mel :: Element\n",
" master element\n",
"sxi :: Vector\n",
" projection point in slave side (typically [-1.0] or [1.0])\n",
"\n",
"Returns\n",
"-------\n",
"mxi :: Vector\n",
" point in master element corresponding to xi in slave\n",
"\n",
"\"\"\"\n",
"function calc_projection_from_slave_to_master(sel, mel, sxi; solver_options...)\n",
" # slave side point\n",
" X1 = interpolate(sel, :Geometry, sxi)\n",
" N1 = interpolate(sel, :Normals, sxi)\n",
" # master element function and their derivatives\n",
" X2(xi) = interpolate(mel, :Geometry, xi)\n",
" dX2(xi) = dinterpolate(mel, :Geometry, xi)\n",
" # residual & solution\n",
" R(xi) = det([X2(xi)-X1 N1])\n",
" dR(xi) = det([dX2(xi) N1])\n",
" mxi = newton(R, dR; solver_options...)\n",
" return [mxi]\n",
"end\n",
"\n",
"\"\"\"\n",
"Find projection from master to slave element.\n",
"\n",
"Parameters\n",
"----------\n",
"sel :: Element\n",
" slave element\n",
"mel :: Element\n",
" master element\n",
"mxi :: Vector\n",
" projection point in master side (typically [-1.0] or [1.0])\n",
"\n",
"Returns\n",
"-------\n",
"sxi :: Vector\n",
" point in slave element corresponding to xi in master\n",
"\"\"\"\n",
"function calc_projection_from_master_to_slave(sel, mel, mxi; solver_options...)\n",
" # slave element functions and their derivatives\n",
" X1(xi) = interpolate(sel, :Geometry, xi)\n",
" dX1(xi) = dinterpolate(sel, :Geometry, xi)\n",
" N1(xi) = interpolate(sel, :Normals, xi)\n",
" dN1(xi) = dinterpolate(sel, :Normals, xi)\n",
" # master side point\n",
" X2 = interpolate(mel, :Geometry, mxi)\n",
" # residual & solution\n",
" R(xi) = det([X1(xi)-X2 N1(xi)])\n",
" dR(xi) = det([dX1(xi) N1(xi)]) + det([X1(xi)-X2 dN1(xi)])\n",
" sxi = newton(R, dR; solver_options...)\n",
" return [sxi]\n",
"end\n",
"\n",
"function has_projection(xi1, xi2)\n",
" l = abs(xi1[2]-xi1[1])[1]\n",
" return l > 1.0e-9\n",
"end\n",
"\n",
"function calc_projection(sel, mel; clamp=true)\n",
" xi1a = calc_projection_from_master_to_slave(sel, mel, [-1.0])\n",
" xi1b = calc_projection_from_master_to_slave(sel, mel, [ 1.0])\n",
" xi2a = calc_projection_from_slave_to_master(sel, mel, [-1.0])\n",
" xi2b = calc_projection_from_slave_to_master(sel, mel, [ 1.0])\n",
" xi1 = Vector[xi1a, xi1b]\n",
" xi2 = Vector[xi2a, xi2b]\n",
" if clamp\n",
" clamp!(xi1, -1, 1)\n",
" clamp!(xi2, -1, 1)\n",
" end\n",
" return xi1, xi2\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Visualize results"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"integrate_segment (generic function with 1 method)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function integrate_segment(sel, mel, xi1, xi2)\n",
" nsel = get_number_of_basis_functions(sel)\n",
" nmel = get_number_of_basis_functions(mel)\n",
" De = zeros(nsel, nsel)\n",
" Me = zeros(nsel, nmel)\n",
" return De, Me\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": [
"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"
],
"text/plain": [
"PyPlot.Figure(PyObject <matplotlib.figure.Figure object at 0x7faed5beb5d0>)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"(-3.0,5.0,-0.1,3.6)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function plot_all()\n",
" figure(figsize=(10, 3))\n",
" for el in Γ₁\n",
" plot_element(el; plot_with_normal=true)\n",
" end\n",
" for el in Γ₂\n",
" plot_element(el; plot_with_normal=false)\n",
" end\n",
" for sel in Γ₁\n",
" for mel in Γ₂\n",
" xi1, xi2 = calc_projection(sel, mel)\n",
" if has_projection(xi1, xi2)\n",
" X1 = interpolate(sel, :Geometry, xi1)\n",
" X2 = interpolate(mel, :Geometry, xi2)\n",
" for s=1:2\n",
" x = [X1[s][1], X2[s][1]]\n",
" y = [X1[s][2], X2[s][2]]\n",
" plot(x, y, \"-kx\")\n",
" end\n",
" De, Me = integrate_segment(sel, mel, xi1, xi2)\n",
" end\n",
" end\n",
" end\n",
" axis(\"equal\")\n",
" ylim(-0.1, 3.6)\n",
" axis(\"off\")\n",
"end\n",
"\n",
"plot_all()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A little experience, raise the degree of elements, smooth geometry, and test projection for 2nd order:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "LoadError",
"evalue": "LoadError: BoundsError: attempt to access (2,)\n at index [2]\nwhile loading In[9], in expression starting on line 13",
"output_type": "error",
"traceback": [
"LoadError: BoundsError: attempt to access (2,)\n at index [2]\nwhile loading In[9], in expression starting on line 13",
"",
" in getindex at tuple.jl:8",
" in get_detJ at /home/jukka/.julia/v0.5/JuliaFEM/src/equations.jl:50",
" in fit_derivative_field! at /home/jukka/.julia/v0.5/JuliaFEM/src/elements.jl:434",
" [inlined code] from In[9]:14",
" in anonymous at no file:0"
]
}
],
"source": [
"# to raise degree of elements and smooth geometry\n",
"function tangent(el, xi)\n",
" normal = interpolate(el, :Normals, xi)\n",
" [0 -1; 1 0]'*normal\n",
"end\n",
"for el in [Γ₁; Γ₂]\n",
" set_degree(el, 2)\n",
" for field in (:Geometry, :Normals)\n",
" push!(el.fields[field], [0.0, 0.0])\n",
" el.fields[field] = el.fields[field][1:get_number_of_basis_functions(el)]\n",
" end\n",
"end\n",
"for el in [Γ₁; Γ₂]\n",
" fit_derivative_field!(el, :Geometry, tangent, Int[1, 2])\n",
"end\n",
"plot_all()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.5.0-dev",
"language": "julia",
"name": "julia-0.5"
},
"language_info": {
"name": "julia",
"version": "0.5.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}