Files
JuliaFEM.jl/docs/tutorials/2015-06-25-elasticity-solver-example.ipynb
T
Jukka Aho 0f0c49da62 Cleanup of obsolete files
A lot of old files from old documentation systems etc. is in package.
These are now removed or moved. Old notebooks are in docs/tutorials.
This PR closes issue #124.
2017-08-05 12:08:46 +03:00

700 lines
19 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Solving elasticity problems using JuliaFEM\n",
"\n",
"Author(s): Jukka Aho\n",
"\n",
"**Abstract**: Solving elasticity equations using JuliaFEM.\n",
"\n",
"### Weak form\n",
"\n",
"Given function spaces\n",
"\\begin{align}\n",
"\\boldsymbol{\\mathcal{U}} & =\\left\\{ \\boldsymbol{u}\\in H^{1}\\left(\\Omega\\right)|\\boldsymbol{u}\\left(\\boldsymbol{X},t\\right)=\\hat{\\boldsymbol{u}}\\left(\\boldsymbol{X},t\\right)\\text{ on }\\Gamma_{\\mathrm{u}}\\right\\} ,\\\\\n",
"\\boldsymbol{\\mathcal{V}} & =\\left\\{ \\delta\\boldsymbol{u}\\in H^{1}\\left(\\Omega\\right)|\\delta\\boldsymbol{u}\\left(\\boldsymbol{X}\\right)=0\\text{ on }\\Gamma_{\\mathrm{u}}\\right\\} ,\n",
"\\end{align}\n",
"find $\\boldsymbol{u}\\in\\boldsymbol{\\mathcal{U}}$ such that\n",
"\\begin{equation}\n",
"\\delta\\mathcal{W}:=\\int_{\\Omega_{0}}\\rho_{0}\\ddot{\\boldsymbol{u}}\\cdot\\delta\\boldsymbol{u}\\,\\mathrm{d}V_{0}+\\int_{\\Omega_{0}}\\boldsymbol{S}:\\delta\\boldsymbol{E}\\,\\mathrm{d}V_{0}-\\int_{\\Omega_{0}}\\hat{\\boldsymbol{b}}_{0}\\cdot\\delta\\boldsymbol{u}\\,\\mathrm{d}V_{0}-\\int_{\\Gamma_{\\sigma}}\\hat{\\boldsymbol{t}}_{0}\\cdot\\delta\\boldsymbol{u}\\,\\mathrm{d}A_{0} =0 \\qquad\\forall\\delta\\boldsymbol{u}\\in\\boldsymbol{\\mathcal{V}}\n",
"\\end{equation}\n",
"\n",
"### Some formulas\n",
"\\begin{align}\n",
"J & =\\det\\left(F\\right)\\\\\n",
"I_{c} & =\\mbox{tr}\\left(C\\right)\\\\\n",
"\\mathbf{C} & =\\mathbf{F}^{\\mathrm{T}}\\mathbf{F}\\\\\n",
"\\mathbf{F} & =\\mathbf{I}+\\nabla\\mathbf{u}\\\\\n",
"\\mathbf{E} & =\\frac{1}{2}\\left(\\mathbf{F}^{\\mathrm{T}}\\mathbf{F}-\\mathbf{I}\\right)\n",
"\\end{align}\n",
"\n",
"### Potential energy\n",
"\n",
"\\begin{equation}\n",
"\\underset{u\\in\\boldsymbol{\\mathcal{U}}}{\\min}\\Pi\\left(\\mathbf{u}\\right)\n",
"\\end{equation}\n",
"\\begin{equation}\n",
"\\Pi\\left(\\mathbf{u}\\right)=\\int_{\\Omega}\\psi\\left(\\mathbf{u}\\right)-\\int_{\\Omega}\\hat{\\mathbf{b}}_{0}\\cdot\\mathbf{u}-\\int_{\\Gamma_{\\sigma}}\\hat{\\mathbf{t}}_{0}\\cdot\\mathbf{u}\\,\\mathrm{d}A_{0}\n",
"\\end{equation}\n",
"\n",
"### Material models\n",
"\n",
"https://en.wikipedia.org/wiki/Strain_energy_density_function\n",
"\n",
"Saint-Venant-Kirchhoff model https://en.wikipedia.org/wiki/Hyperelastic_material\n",
"\\begin{equation}\n",
"\\psi\\left(\\mathbf{E}\\right)=\\frac{\\lambda}{2}\\left[\\mbox{tr}\\left(\\mathbf{E}\\right)\\right]^{2}+\\mu\\mbox{tr}\\left(\\mathbf{E}^2\\right)\n",
"\\end{equation}\n",
"\n",
"neo-Hookean material https://en.wikipedia.org/wiki/Neo-Hookean_solid\n",
"\\begin{equation}\n",
"\\psi=\\frac{\\mu}{2}\\left(I_{c}-3\\right)-\\mu\\ln\\left(J\\right)+\\frac{\\lambda}{2}\\ln\\left(J\\right)^{2}\n",
"\\end{equation}"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"using JuliaFEM.API: Model, Material, add_material!, LoadCase, add_element_set!, ForceBC, DisplacementBC\n",
"using JuliaFEM.API: add_boundary_condition!, add_load_case!, add_solver!\n",
"using JuliaFEM.Interfaces: solve!\n",
"using JuliaFEM.Preprocess: parse_abaqus"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: Parsing nodes\n",
"INFO: Parsing elements. Type: Tet10\n",
"INFO: Parsing elements. Type: Tri6\n",
"INFO: Creating elset BC1\n",
"INFO: Creating elset BC2\n",
"INFO: model loaded.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" 4.209444 seconds (19.12 M allocations: 565.872 MB, 11.55% gc time)\n"
]
}
],
"source": [
"@time begin\n",
" # Linear models\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_8789_P1.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_16436_P1.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_27343_P1.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_45510_P1.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_75470_P1.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/wrench/wrench_128903_P1.inp\")\n",
"\n",
" # Quadratic models\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_19611_P2.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_55950_P2.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"/Temp/piston_107168_P2.inp\")\n",
" #model = open(JuliaFEM.Core.parse_abaqus, \"../geometry/piston/piston_345757_P2.inp\")\n",
"\n",
" mesh = open(parse_abaqus, \"/Temp/piston_107168_P2.inp\")\n",
" model = Model(\"piston model\", mesh)\n",
" info(\"model loaded.\")\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"JuliaFEM.API.Material(\"steel\",Dict(\"poissons ratio\"=>0.3,\"youngs modulus\"=>210000.0))"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mat = Material(\"steel\")\n",
"mat[\"youngs modulus\"] = 210.0e3\n",
"mat[\"poissons ratio\"] = 0.3\n",
"add_material!(model, \"PISTON\", mat)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{ASCIIString,1}:\n",
" \"PISTON\""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"simulation = LoadCase(:ElasticityProblem)\n",
"\n",
"# simulation = Simulation(:ElasticityProblem, \"elasticity equations\")\n",
"# add_element_set!(simulation, \"PISTON\")\n",
"# add_boundary_condition!(simulation, bc1, bc2)\n",
"# add_simulation!(model, simulation)\n",
"# add_solver!(simulation, :DirectSolver)\n",
"# solve!(model, \"elasticity equations\", 0.0)\n",
"# solve!(model, \"heat equations\", 0.0)\n",
"# solve!(model, \"solve equations 3\", 0.0)\n",
"\n",
"add_element_set!(simulation, \"PISTON\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{JuliaFEM.API.DirichletBC,1}:\n",
" JuliaFEM.API.DirichletBC(\"BC2\",\"displacement\"=>0.0)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"traction = Vector{Float64}[[0.0, 0.0, -10.0] for i in 1:6]\n",
"bc1 = ForceBC(\"BC1\", \"displacement traction force\" => traction)\n",
"bc2 = DisplacementBC(\"BC2\", \"displacement\" => 0.0)\n",
"\n",
"# JuliaFEM.API.add_boundary_condition!(prob, bc1, bc2)\n",
"add_boundary_condition!(simulation, bc1)\n",
"add_boundary_condition!(simulation, bc2)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"JuliaFEM.API.LoadCase(:ElasticityProblem,[JuliaFEM.API.NeumannBC(\"BC1\",\"displacement traction force\"=>[[0.0,0.0,-10.0],[0.0,0.0,-10.0],[0.0,0.0,-10.0],[0.0,0.0,-10.0],[0.0,0.0,-10.0],[0.0,0.0,-10.0]])],[JuliaFEM.API.DirichletBC(\"BC2\",\"displacement\"=>0.0)],:DirectSolver,ASCIIString[\"PISTON\"])"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"add_solver!(simulation, :DirectSolver)\n",
"add_load_case!(model, \"elasticity equations\", simulation)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"solver = JuliaFEM.Interfaces.get_solver(model, \"elasticity equations\", 0.0);"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"JuliaFEM.Core.Element{JuliaFEM.Core.Tet10}([1,2,3,4,5,6,7,8,9,10],Dict{ASCIIString,JuliaFEM.Core.Field{A<:Union{JuliaFEM.Core.Continuous,JuliaFEM.Core.Discrete},B<:Union{JuliaFEM.Core.Constant,JuliaFEM.Core.Variable},C<:Union{JuliaFEM.Core.TimeInvariant,JuliaFEM.Core.TimeVariant}}}(\"poissons ratio\"=>JuliaFEM.Core.Field{JuliaFEM.Core.Discrete,JuliaFEM.Core.Constant,JuliaFEM.Core.TimeInvariant}(0.3),\"geometry\"=>JuliaFEM.Core.Field{JuliaFEM.Core.Discrete,JuliaFEM.Core.Variable,JuliaFEM.Core.TimeInvariant}([[13.96894,1.54855,-2.99382],[15.71724,2.88794,-2.79243],[14.76115,1.1419,-1.23125],[15.93754,1.0623,-2.82067],[14.84309,2.21825,-2.89313],[15.2392,2.01492,-2.01184],[14.36505,1.34523,-2.11254],[14.95324,1.30543,-2.90725],[15.82739,1.97512,-2.80655],[15.34935,1.1021,-2.02596]]),\"youngs modulus\"=>JuliaFEM.Core.Field{JuliaFEM.Core.Discrete,JuliaFEM.Core.Constant,JuliaFEM.Core.TimeInvariant}(210000.0)))"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"celements = solver.field_problems[1].elements;\n",
"celements[1]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: 0 surface elements\n"
]
}
],
"source": [
"surface_elements = filter((e) -> isa(e, JuliaFEM.Core.Element{JuliaFEM.Core.Tri6}), celements)\n",
"info(\"$(length(surface_elements)) surface elements\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"62454"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"length(celements)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: # of field problems: 1\n",
"INFO: # of boundary problems: 1\n",
"INFO: Starting iteration 1\n",
"INFO: Assembling field problems...\n",
"INFO: Assembling body 1...\n",
"INFO: Assembly: 10.0 % done. \n",
"INFO: Assembly: 20.0 % done. \n",
"INFO: Assembly: 30.0 % done. \n",
"INFO: Assembly: 40.0 % done. \n",
"INFO: Assembly: 50.0 % done. \n",
"INFO: Assembly: 60.0 % done. \n",
"INFO: Assembly: 70.0 % done. \n",
"INFO: Assembly: 80.0 % done. \n",
"INFO: Assembly: 90.0 % done. \n",
"INFO: Assembly: 100.0 % done. \n",
"INFO: Assembling boundary problems...\n",
"INFO: Assembling boundary 1...\n",
"INFO: Assembly: 10.0 % done. \n",
"INFO: Assembly: 20.0 % done. \n",
"INFO: Assembly: 30.0 % done. \n",
"INFO: Assembly: 40.0 % done. \n",
"INFO: Assembly: 50.0 % done. \n",
"INFO: Assembly: 60.0 % done. \n",
"INFO: Assembly: 70.0 % done. \n",
"INFO: Assembly: 80.0 % done. \n",
"INFO: Assembly: 90.0 % done. \n",
"INFO: Assembly: 100.0 % done. \n",
"INFO: Solving system\n",
"INFO: all dofs = 321504\n",
"INFO: interior dofs = 312936\n",
"INFO: boundary dofs = 8568\n",
"INFO: preparation in 3.385999917984009 seconds\n",
"INFO: displacement on boundary solved.\n",
"INFO: norm[u_boundary_dofs] = 0.0\n",
"INFO: homogeneous dirichlet boundary\n",
"INFO: solve boundary = 0.42100000381469727\n",
"INFO: factorizations done in 14.133000135421753 seconds\n",
"INFO: solved interior in 0.2969999313354492 seconds. norm = 0.0\n",
"INFO: timing info for non-linear iteration:\n"
]
},
{
"data": {
"text/plain": [
"(1,true)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: boundary assembly : 2.1679999828338623\n",
"INFO: field assembly : 279.9069998264313\n",
"INFO: dump matrices to disk : 0.0\n",
"INFO: solve problem : 19.37600016593933\n",
"INFO: update element data : 1.6999998092651367\n",
"INFO: non-linear iteration : 303.1509997844696\n",
"INFO: solver finished in 304.5089998245239 seconds.\n"
]
}
],
"source": [
"solve!(model, \"elasticity equations\", 0.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Saving results to file"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<Grid Name=\"Grid\">\n",
" <Time Value=\"0\"/>\n",
"</Grid>\n"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"xdoc, xmodel = JuliaFEM.Postprocess.xdmf_new_model()\n",
"temporal_collection = JuliaFEM.Postprocess.xdmf_new_temporal_collection(xmodel)\n",
"grid = JuliaFEM.Postprocess.xdmf_new_grid(temporal_collection; time=0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Save geometry to xdmf file"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: number of nodes in model: 8789\n",
"INFO: Number of elements in model: 31437\n"
]
}
],
"source": [
"nnodes = length(model[\"nodes\"])\n",
"info(\"number of nodes in model: $nnodes\")\n",
"\n",
"X = zeros(3, nnodes)\n",
"for nid in keys(model[\"nodes\"])\n",
" X[:, perm[nid]] = model[\"nodes\"][nid]\n",
"end\n",
"\n",
"nelements = length(model[\"elsets\"][\"PISTON\"])\n",
"info(\"Number of elements in model: $nelements\")\n",
"elmap = zeros(Int64, 5, nelements)\n",
"#elmap[1,:] = 0x0026\n",
"elmap[1,:] = 0x6\n",
"for (i, elid) in enumerate(model[\"elsets\"][\"PISTON\"])\n",
" elmap[2:end,i] = Int64[perm[nid] for nid in model[\"elements\"][elid]]\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"JuliaFEM.Postprocess.xdmf_new_mesh(grid, X, elmap)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Save nodal data to model"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(3,8789)"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"using JuliaFEM.Core: get_connectivity\n",
"\n",
"u = zeros(3, nnodes)\n",
"\n",
"for element in values(elements)\n",
" isa(element, Element{Tet4}) || continue\n",
" connectivity = get_connectivity(element)\n",
" field = element[\"displacement\"](0.0)\n",
" for (i, nid) in enumerate(connectivity)\n",
" u[:, nid] = field[i]\n",
" end\n",
"end\n",
"size(u)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"true"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"JuliaFEM.Postprocess.xdmf_new_field(grid, \"Displacement\", \"nodes\", u)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1525505"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"JuliaFEM.Postprocess.xdmf_save_model(xdoc, \"/tmp/piston_8789_P1.xmf\")"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3x10 Array{Float64,2}:\n",
" 0.0582911 0.339694 0.431768 … 0.124351 0.346492 0.000617283\n",
" 0.0900323 0.22174 0.433814 0.140503 0.275036 0.0044649 \n",
" 0.0838928 -0.148224 0.00262483 -0.11171 0.0843743 -0.0175412 "
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u[:, 1:10]"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1x3 Array{Float64,2}:\n",
" -0.0471355 -0.468786 -0.222571"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"minimum(u, 2)'"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1x3 Array{Float64,2}:\n",
" 0.511168 0.563004 0.66328"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"maximum(u, 2)'"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"38.52232721814439"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"piston_8789_P1_solution_norm = 38.52232721814439"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"@assert isapprox(norm(vec(u)), piston_8789_P1_solution_norm)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.4.1",
"language": "julia",
"name": "julia-0.4"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.4.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}