mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-10-02 14:23:58 +00:00
1278 lines
44 KiB
Plaintext
1278 lines
44 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Solving elasticity problems using JuliaFEM\n",
|
||
"\n",
|
||
"Author(s): Jukka Aho\n",
|
||
"\n",
|
||
"**Abstract**: A workflow to solve typical elasticity problem. This document also tries to give some quidelines how to develop JuliaFEM."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Bottom-up design\n",
|
||
"\n",
|
||
"We go piece by piece starting from something simple and going up to more complicated programming model."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"*Design principle 1*: we introduce new ideas using Notebooks."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"*Design principle 2*: we use ``Logging``. Forget ``println``."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Logger(root,DEBUG,Pipe(open, 0 bytes waiting),root)"
|
||
]
|
||
},
|
||
"execution_count": 1,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
" in depwarn at /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib\n",
|
||
" in int32 at deprecated.jl:49\n",
|
||
" in recv at /Users/jukka/.julia/v0.4/ZMQ/src/ZMQ.jl:617\n",
|
||
" in recv_ipython at /Users/jukka/.julia/v0.4/IJulia/src/msg.jl:63\n",
|
||
" in eventloop at /Users/jukka/.julia/v0.4/IJulia/src/IJulia.jl:120\n",
|
||
" in anonymous at task.jl:365\n",
|
||
"while loading /Users/jukka/.julia/v0.4/IJulia/src/kernel.jl, in expression starting on line 35\n",
|
||
"WARNING: int32(x) is deprecated, use Int32(x) instead.\n",
|
||
" in depwarn at /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib\n",
|
||
" in int32 at deprecated.jl:49\n",
|
||
" in recv at /Users/jukka/.julia/v0.4/ZMQ/src/ZMQ.jl:617\n",
|
||
" in recv_ipython at /Users/jukka/.julia/v0.4/IJulia/src/msg.jl:63\n",
|
||
" in eventloop at /Users/jukka/.julia/v0.4/IJulia/src/IJulia.jl:120\n",
|
||
" in anonymous at task.jl:365\n",
|
||
"while loading /Users/jukka/.julia/v0.4/IJulia/src/kernel.jl, in expression starting on line 35\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"using JuliaFEM\n",
|
||
"using Logging\n",
|
||
"Logging.configure(level=DEBUG)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"*Design principle 3*: we write docstrings using [numpy style](https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt).\n",
|
||
"\n",
|
||
"*Design principle 4*: we don't use greek characters in code which is implemented to JuliaFEM. In notebooks they are ok.\n",
|
||
"\n",
|
||
"*Design principle 5*: we use 4 space indentation like in Python.\n",
|
||
"\n",
|
||
"Our task is: for given $\\mathbf{u}$ calculate $\\mathbf{R}(\\mathbf{u}) = \\mathbf{T}(\\mathbf{u}) - \\mathbf{F}(\\mathbf{u})$ and it's partial derivative with respect to $\\mathbf{u}$, i.e. $\\partial \\mathbf{R}(\\mathbf{u}) / \\partial \\mathbf{u}$."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"jacobian (generic function with 1 method)"
|
||
]
|
||
},
|
||
"execution_count": 2,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"function Wint_integrand(el, ip)\n",
|
||
" xi = ip.xi\n",
|
||
" dbasisdX = JuliaFEM.get_dbasisdX(el, ip)\n",
|
||
" u = el.attributes[\"displacement\"]\n",
|
||
"\n",
|
||
" # kinematics\n",
|
||
" gradu = u*dbasisdX\n",
|
||
" F = I + gradu\n",
|
||
" E = 1/2*(gradu' + gradu + gradu'*gradu)\n",
|
||
"\n",
|
||
" # constitutive equation\n",
|
||
" lambda = JuliaFEM.interpolate(el, \"lambda\", xi)\n",
|
||
" mu = JuliaFEM.interpolate(el, \"mu\", xi)\n",
|
||
" S = lambda*trace(E)*I + 2*mu*E\n",
|
||
" P = F*S\n",
|
||
" T = P*dbasisdX'\n",
|
||
" return T\n",
|
||
"end\n",
|
||
"\n",
|
||
"Wint = JuliaFEM.integrate(Wint_integrand)\n",
|
||
"\n",
|
||
"# calculate partial derivatives of R with respect to field \"displacement\"\n",
|
||
"jacobian = JuliaFEM.linearize(Wint, \"displacement\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"That was our geometrically nonlinear elasticity solver. Note how we used automatic differentiation to linearize residual vector.\n",
|
||
"\n",
|
||
"*Design principle 6*: we test our code. We use FactCheck for testing."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"metadata": {
|
||
"collapsed": true
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"using FactCheck"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"scrolled": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"test solve one element model\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"19-Aug 18:39:44:DEBUG:root:Converged in 6 iterations.\n",
|
||
"19-Aug 18:39:44:DEBUG:root:solution vector: \n",
|
||
" [0.0 -0.3991450609547433 -0.07228582695592461 0.0\n",
|
||
" 0.0 -2.1779892317073504 -2.222244754401764 0.0]\n",
|
||
"19-Aug 18:39:44:DEBUG:root:norm of u: 3.1292483947150047\n",
|
||
"19-Aug 18:39:45:DEBUG:root:Converged in 6 iterations.\n",
|
||
"19-Aug 18:39:45:DEBUG:root:solution vector: \n",
|
||
" [0.0 0.7433248532717796 1.048521014723486 0.0\n",
|
||
" 0.0 -2.085766534304891 -1.9606633242166027 0.0]\n",
|
||
"19-Aug 18:39:45:DEBUG:root:norm of u: 3.1292483947150056\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"2 facts verified.\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"delayed_handler (generic function with 4 methods)"
|
||
]
|
||
},
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"function get_test_element()\n",
|
||
" # set up one linear quadrangle element\n",
|
||
" basis(xi) = [\n",
|
||
" (1-xi[1])*(1-xi[2])/4\n",
|
||
" (1+xi[1])*(1-xi[2])/4\n",
|
||
" (1+xi[1])*(1+xi[2])/4\n",
|
||
" (1-xi[1])*(1+xi[2])/4]\n",
|
||
" dbasis(xi) = [-(1-xi[2])/4.0 -(1-xi[1])/4.0\n",
|
||
" (1-xi[2])/4.0 -(1+xi[1])/4.0\n",
|
||
" (1+xi[2])/4.0 (1+xi[1])/4.0\n",
|
||
" -(1+xi[2])/4.0 (1-xi[1])/4.0]\n",
|
||
" integration_points = [\n",
|
||
" JuliaFEM.IntegrationPoint(1.0/sqrt(3.0)*[-1, -1], 1.0, Dict()),\n",
|
||
" JuliaFEM.IntegrationPoint(1.0/sqrt(3.0)*[ 1, -1], 1.0, Dict()),\n",
|
||
" JuliaFEM.IntegrationPoint(1.0/sqrt(3.0)*[ 1, 1], 1.0, Dict()),\n",
|
||
" JuliaFEM.IntegrationPoint(1.0/sqrt(3.0)*[-1, 1], 1.0, Dict())]\n",
|
||
" attributes = Dict()\n",
|
||
" element_id = 1\n",
|
||
" node_ids = [1, 2, 3, 4]\n",
|
||
" e = JuliaFEM.Element(element_id, node_ids, basis, dbasis, integration_points, attributes)\n",
|
||
" E = 90.0\n",
|
||
" nu = 0.25\n",
|
||
" mu = E/(2*(1+nu))\n",
|
||
" la = E*nu/((1+nu)*(1-2*nu))\n",
|
||
" la = 2*la*mu/(la + 2*mu)\n",
|
||
" e.attributes[\"coordinates\"] = [0.0 0.0; 10.0 0.0; 10.0 1.0; 0.0 1.0]'\n",
|
||
" e.attributes[\"lambda\"] = la\n",
|
||
" e.attributes[\"mu\"] = mu\n",
|
||
" e.attributes[\"displacement\"] = [0.0 0.0; 0.0 0.0; 0.0 0.0; 0.0 0.0]'\n",
|
||
" return e\n",
|
||
"end\n",
|
||
"\n",
|
||
"facts(\"test solve one element model\") do\n",
|
||
"\n",
|
||
" e = get_test_element()\n",
|
||
" F = [0.0 0.0; 0.0 0.0; 0.0 -2.0; 0.0 0.0]'\n",
|
||
"\n",
|
||
" du = zeros(2, 4)\n",
|
||
"\n",
|
||
" free_dofs = [3, 4, 5, 6]\n",
|
||
" for i=1:10\n",
|
||
" R = Wint(e)\n",
|
||
" K = jacobian(e)\n",
|
||
" du[free_dofs] = K[free_dofs, free_dofs] \\ -(R - F)[free_dofs]\n",
|
||
" e.attributes[\"displacement\"] += du\n",
|
||
" if norm(du) < 1.0e-9\n",
|
||
" Logging.debug(\"Converged in $i iterations.\")\n",
|
||
" break\n",
|
||
" end\n",
|
||
" end\n",
|
||
"\n",
|
||
" # Tested against Elmer solution\n",
|
||
" u = e.attributes[\"displacement\"]\n",
|
||
" Logging.debug(\"solution vector: \\n $u\")\n",
|
||
" @fact u[2, 3] --> roughly(-2.222244754401764)\n",
|
||
" norm1 = norm(u)\n",
|
||
" Logging.debug(\"norm of u: $(norm(u))\")\n",
|
||
"\n",
|
||
" # We rotate model a bit and make sure that norm remains same\n",
|
||
" phi = 30/180*pi\n",
|
||
" rmat = [\n",
|
||
" cos(phi) -sin(phi)\n",
|
||
" sin(phi) cos(phi)]\n",
|
||
" e.attributes[\"coordinates\"] = rmat*e.attributes[\"coordinates\"]\n",
|
||
" F = rmat*F\n",
|
||
"\n",
|
||
" e.attributes[\"displacement\"] = [0.0 0.0; 0.0 0.0; 0.0 0.0; 0.0 0.0]'\n",
|
||
" du = zeros(2, 4)\n",
|
||
" for i=1:10\n",
|
||
" R = Wint(e)\n",
|
||
" K = jacobian(e)\n",
|
||
" du[free_dofs] = K[free_dofs, free_dofs] \\ -(R - F)[free_dofs]\n",
|
||
" e.attributes[\"displacement\"] += du\n",
|
||
" if norm(du) < 1.0e-9\n",
|
||
" Logging.debug(\"Converged in $i iterations.\")\n",
|
||
" break\n",
|
||
" end\n",
|
||
" end\n",
|
||
" u = e.attributes[\"displacement\"]\n",
|
||
" Logging.debug(\"solution vector: \\n $u\")\n",
|
||
" Logging.debug(\"norm of u: $(norm(u))\")\n",
|
||
" @fact norm(u) --> roughly(norm1) \n",
|
||
"end"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"assemble_element! (generic function with 1 method)"
|
||
]
|
||
},
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"function assemble_element!(ass::JuliaFEM.Assembly, el::JuliaFEM.Element)\n",
|
||
"\n",
|
||
" gdofs = ass.gdofs[el.id]\n",
|
||
" R = Wint(el)\n",
|
||
" K = jacobian(el)\n",
|
||
" dofs = length(R)\n",
|
||
"\n",
|
||
" for i=1:dofs\n",
|
||
" for j=1:dofs\n",
|
||
" push!(ass.I, gdofs[i])\n",
|
||
" push!(ass.J, gdofs[j])\n",
|
||
" push!(ass.A, K[i,j])\n",
|
||
" end\n",
|
||
" push!(ass.i, gdofs[i])\n",
|
||
" push!(ass.b, R[i])\n",
|
||
" end\n",
|
||
"end"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Time to test again. From last test we know that correct solution is\n",
|
||
"\n",
|
||
" [0.0 -0.39914506095474317 -0.07228582695592449 0.0\n",
|
||
" 0.0 -2.1779892317073504 -2.222244754401764 0.0]\n",
|
||
"\n",
|
||
"This time we assemble global stiffness matrix in different order, 2 3 4 1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"one element assembly\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"19-Aug 18:39:46:DEBUG:root:Adding nodes to array\n",
|
||
"19-Aug 18:39:46:DEBUG:root:Starting iteration 1\n",
|
||
"19-Aug 18:39:46:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Solution norm = 3.0900221367289986\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Starting iteration 2\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Solution norm = 0.3212131602153472\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Starting iteration 3\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Solution norm = 0.04043178193999703\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Starting iteration 4\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Solution norm = 0.0009291101052105739\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Starting iteration 5\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Solution norm = 1.5638899027804743e-7\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Starting iteration 6\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Solution norm = 1.0464940956129567e-14\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Converged in 6 iterations.\n",
|
||
"19-Aug 18:39:47:DEBUG:root:Displacement of element = \n",
|
||
"[0.0 -0.39914506095474334 -0.0722858269559246 0.0\n",
|
||
" 0.0 -2.1779892317073504 -2.222244754401764 0.0]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"1 fact verified.\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"delayed_handler (generic function with 4 methods)"
|
||
]
|
||
},
|
||
"execution_count": 6,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"facts(\"one element assembly\") do\n",
|
||
" # Create model\n",
|
||
" Logging.debug(\"Adding nodes to array\")\n",
|
||
" el = get_test_element()\n",
|
||
" \n",
|
||
" for i=1:10\n",
|
||
" Logging.debug(\"Starting iteration $i\")\n",
|
||
" ass = JuliaFEM.Assembly(Int64[], Int64[], Float64[], Int64[], Float64[], Dict{Int64,Array{Int64,1}}())\n",
|
||
" ass.gdofs[el.id] = [1, 2, 3, 4, 5, 6, 7, 8]\n",
|
||
" Logging.debug(\"Assembling\")\n",
|
||
" assemble_element!(ass, el)\n",
|
||
"\n",
|
||
" # Boundary conditions\n",
|
||
" F = [0.0 0.0; 0.0 0.0; 0.0 -2.0; 0.0 0.0]'\n",
|
||
" F = F[:]\n",
|
||
" free_dofs = [3, 4, 5, 6]\n",
|
||
"\n",
|
||
" # solution\n",
|
||
" K = sparse(ass.I, ass.J, ass.A)\n",
|
||
" R = full(sparsevec(ass.i, ass.b))\n",
|
||
" R = R - F\n",
|
||
" du = zeros(8)\n",
|
||
" du[free_dofs] = K[free_dofs, free_dofs] \\ -R[free_dofs]\n",
|
||
"\n",
|
||
" Logging.debug(\"Solution norm = $(norm(du))\")\n",
|
||
"\n",
|
||
" # update solution back to elements\n",
|
||
" eldu = du[ass.gdofs[el.id]]\n",
|
||
" eldu = reshape(eldu, (2, round(Int, length(eldu)/2)))\n",
|
||
" el.attributes[\"displacement\"] += eldu\n",
|
||
" if norm(du) < 1.0e-9\n",
|
||
" Logging.debug(\"Converged in $i iterations.\")\n",
|
||
" break\n",
|
||
" end\n",
|
||
" end\n",
|
||
" disp = el.attributes[\"displacement\"]\n",
|
||
" Logging.debug(\"Displacement of element = \\n$disp\")\n",
|
||
" @fact norm(disp) --> roughly(3.1292483947150043)\n",
|
||
"end"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Seems to be working. But we still need to handle boundary conditions more \"cleverly\" and generalize assembly to several elements (which is not problem).\n",
|
||
"\n",
|
||
"First of all, essential boundary conditions are nothing more than equality constraints saying that value for some degree of freedom is fixed. Elimination is just a special case when this value equals to zero. There is couple of different strategies to handle essential boundary conditions. One option is to force them using Lagrange multipliers which can also be used to create all kind of kinematic constraints also. (For example, contact can be considered as a kinematic constraint.) Another option is to manipulate matrix such a way that constraint is satisfied.\n",
|
||
"\n",
|
||
"Because we are now going \"bottom-up\", we develop something extremely simple that however deals with the problem:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"type BC\n",
|
||
" dofs :: Array{Int64, 1}\n",
|
||
" values :: Array{Float64, 1}\n",
|
||
"end"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"create_ldof2gdofmap (generic function with 1 method)"
|
||
]
|
||
},
|
||
"execution_count": 8,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"\"\"\"\n",
|
||
"Create local dof to global dof mapping for given elements\n",
|
||
"\"\"\"\n",
|
||
"function create_ldof2gdofmap(elements, field)\n",
|
||
"\n",
|
||
" ndofs = size(elements[1].attributes[field], 1)\n",
|
||
" \n",
|
||
" all_node_ids = Int64[]\n",
|
||
" for el in elements\n",
|
||
" for nid in el.node_ids\n",
|
||
" push!(all_node_ids, nid)\n",
|
||
" end\n",
|
||
" end\n",
|
||
" all_node_ids = unique(all_node_ids)\n",
|
||
"\n",
|
||
" # Assign global dof for each node\n",
|
||
" pdim = 1\n",
|
||
" ngdofs = Dict{Int64, Array{Int64,1}}()\n",
|
||
" for nid in all_node_ids\n",
|
||
" ngdofs[nid] = collect(pdim:pdim+ndofs-1)\n",
|
||
" pdim += ndofs\n",
|
||
" end\n",
|
||
"\n",
|
||
" return ngdofs\n",
|
||
"end"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"scrolled": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"solve one element problem\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"19-Aug 18:49:12:DEBUG:root:Dict(4=>[7,8],2=>[3,4],3=>[5,6],1=>[1,2])\n",
|
||
"19-Aug 18:49:13:INFO:root:solve!: dofs per node: 2\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Problem size = 8\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Starting iteration 1\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Added 5 Lagrange multipliers to model\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solving system of equations. Total size = 12\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solution norm du = 3.0900221367289444\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Starting iteration 2\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Added 5 Lagrange multipliers to model\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solving system of equations. Total size = 12\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solution norm du = 0.32121316021534796\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Starting iteration 3\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Added 5 Lagrange multipliers to model\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solving system of equations. Total size = 12\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solution norm du = 0.040431781940014504\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Starting iteration 4\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Added 5 Lagrange multipliers to model\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solving system of equations. Total size = 12\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solution norm du = 0.0009291101052065917\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Starting iteration 5\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Added 5 Lagrange multipliers to model\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solving system of equations. Total size = 12\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solution norm du = 1.5638899136781228e-7\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Starting iteration 6\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Assembling\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Added 5 Lagrange multipliers to model\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solving system of equations. Total size = 12\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Solution norm du = 1.0913504694802626e-14\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Converged in 6 iterations.\n",
|
||
"19-Aug 18:49:13:DEBUG:root:Displacement of element = \n",
|
||
"[0.0 -0.39914506095474345 -0.07228582695592467 0.0\n",
|
||
" 0.0 -2.177989231707351 -2.222244754401765 0.0]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"1 fact verified.\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"delayed_handler (generic function with 4 methods)"
|
||
]
|
||
},
|
||
"execution_count": 16,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"function solve!(elements, dofmap, neumann_bcs, dirichlet_bcs; ndofs=2, max_iterations=10)\n",
|
||
"\n",
|
||
" Logging.info(\"solve!: dofs per node: $ndofs\")\n",
|
||
" pdim = length(dofmap)*ndofs\n",
|
||
" Logging.debug(\"Problem size = $pdim\")\n",
|
||
"\n",
|
||
" # Assign global dofs for elements\n",
|
||
" gdofs = Dict{Int64, Array{Int64,1}}()\n",
|
||
" for el in elements\n",
|
||
" gdofs[el.id] = Int64[]\n",
|
||
" for nid in el.node_ids\n",
|
||
" for ndof in dofmap[nid]\n",
|
||
" push!(gdofs[el.id], ndof)\n",
|
||
" end\n",
|
||
" end\n",
|
||
" end\n",
|
||
"\n",
|
||
" ass = JuliaFEM.Assembly(Int64[], Int64[], Float64[], Int64[], Float64[], gdofs)\n",
|
||
"\n",
|
||
" for iter=1:max_iterations\n",
|
||
" Logging.debug(\"Starting iteration $iter\")\n",
|
||
" ass.I = []\n",
|
||
" ass.J = []\n",
|
||
" ass.A = []\n",
|
||
" ass.i = []\n",
|
||
" ass.b = []\n",
|
||
" \n",
|
||
" Logging.debug(\"Assembling\")\n",
|
||
" for el in elements\n",
|
||
" assemble_element!(ass, el)\n",
|
||
" end\n",
|
||
"\n",
|
||
" i = 1\n",
|
||
" Logging.debug(\"Adding Dirichlet boundary conditions using Lagrange multipliers\")\n",
|
||
" # Dirichlet boundary conditions\n",
|
||
" for bc in dirichlet_bcs\n",
|
||
" for (dof, val) in zip(bc.dofs, bc.values)\n",
|
||
" #Logging.debug(\"dof $dof => $val\")\n",
|
||
" push!(ass.I, dof)\n",
|
||
" push!(ass.J, pdim+i)\n",
|
||
" push!(ass.A, 1)\n",
|
||
" push!(ass.I, pdim+i)\n",
|
||
" push!(ass.J, dof)\n",
|
||
" push!(ass.A, 1)\n",
|
||
" push!(ass.i, pdim+i)\n",
|
||
" push!(ass.b, 0)\n",
|
||
" i += 1\n",
|
||
" end\n",
|
||
" end\n",
|
||
" Logging.debug(\"Added $i Lagrange multipliers to model\")\n",
|
||
" i -= 1\n",
|
||
"\n",
|
||
" Logging.debug(\"Adding Neumann boundary conditions\")\n",
|
||
" F = zeros(pdim+i)\n",
|
||
" # Neumann boundary conditions\n",
|
||
" for bc in neumann_bcs\n",
|
||
" for (dof, val) in zip(bc.dofs, bc.values)\n",
|
||
" F[dof] += val\n",
|
||
" end\n",
|
||
" end\n",
|
||
"\n",
|
||
" Logging.debug(\"Solving system of equations. Total size = $(pdim+i)\")\n",
|
||
" # solution\n",
|
||
" K = sparse(ass.I, ass.J, ass.A)\n",
|
||
" R = full(sparsevec(ass.i, ass.b))\n",
|
||
" R = R - F\n",
|
||
"\n",
|
||
" du = K \\ -R\n",
|
||
"\n",
|
||
" #du = reshape(du, 2, 6)\n",
|
||
" solnorm = norm(du[1:pdim])\n",
|
||
" #Logging.debug(\"du = $du\")\n",
|
||
" Logging.debug(\"Solution norm du = $solnorm\")\n",
|
||
"\n",
|
||
" # update solution back to elements\n",
|
||
" for el in elements\n",
|
||
" #Logging.debug(\"update element $(el.id)\")\n",
|
||
" eldisp = el.attributes[\"displacement\"]\n",
|
||
" #Logging.debug(\"displacement before update $(el.id) : \\n$eldisp\")\n",
|
||
" eldu = du[ass.gdofs[el.id]]\n",
|
||
" eldu = reshape(eldu, (ndofs, round(Int, length(eldu)/ndofs)))\n",
|
||
" #Logging.debug(\"eldu for element $(el.id) \\n$eldu\")\n",
|
||
" el.attributes[\"displacement\"] += eldu\n",
|
||
" eldisp = el.attributes[\"displacement\"]\n",
|
||
" #Logging.debug(\"displacement after update $(el.id) : \\n$eldisp\")\n",
|
||
"\n",
|
||
" end\n",
|
||
" if solnorm < 1.0e-9\n",
|
||
" Logging.debug(\"Converged in $iter iterations.\")\n",
|
||
" break\n",
|
||
" end\n",
|
||
" end\n",
|
||
"\n",
|
||
"end\n",
|
||
"\n",
|
||
"ENV[\"COLUMNS\"] = 160\n",
|
||
"\n",
|
||
"facts(\"solve one element problem\") do\n",
|
||
" # Create model\n",
|
||
" el = get_test_element()\n",
|
||
" elements = [el]\n",
|
||
" # Initialize elements ready for solution\n",
|
||
" for el in elements\n",
|
||
" eldim, elnodes = size(el.attributes[\"coordinates\"])\n",
|
||
" el.attributes[\"displacement\"] = zeros(2, elnodes)\n",
|
||
" end\n",
|
||
" dofmap = create_ldof2gdofmap(elements, \"displacement\")\n",
|
||
" Logging.debug(dofmap)\n",
|
||
" # Boundary conditions\n",
|
||
" # here we want to create nodal force for third dof, that is, node id 2, second dof\n",
|
||
" bc1 = BC([dofmap[3][2]], [-2.0])\n",
|
||
" # dirichlet bc, set dx=dy=0 on support\n",
|
||
" bc2 = BC([dofmap[1][1], dofmap[1][2], dofmap[4][1], dofmap[4][2]], [0.0, 0.0, 0.0, 0.0])\n",
|
||
" solve!(elements, dofmap, [bc1], [bc2]; max_iterations=7)\n",
|
||
" disp = elements[1].attributes[\"displacement\"]\n",
|
||
" Logging.debug(\"Displacement of element = \\n$disp\")\n",
|
||
" @fact norm(disp) --> roughly(3.1292483947150043)\n",
|
||
"end\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Top-down design\n",
|
||
"\n",
|
||
"Next we see this problem from \"other direction\", by parsing ABAQUS .inp file and making 3d simulation."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"19-Aug 18:49:21:INFO:root:Registered handlers: Any[\"ELEMENT\",\"NODE\",\"NSET\"]\n",
|
||
"WARNING: beginswith is deprecated, use startswith instead.\n"
|
||
]
|
||
},
|
||
{
|
||
"ename": "LoadError",
|
||
"evalue": "LoadError: MethodError: `convert` has no method matching convert(::Type{SubString{ASCIIString}}, ::Dict{Any,Any})\nThis may have arisen from a call to the constructor SubString{ASCIIString}(...),\nsince type constructors fall back to convert methods.\nClosest candidates are:\n call{T}(::Type{T}, ::Any)\n convert{T<:AbstractString}(::Type{T<:AbstractString}, !Matched::AbstractArray{Char,1})\n convert{T<:AbstractString}(::Type{SubString{T<:AbstractString}}, !Matched::T<:AbstractString)\n ...\nwhile loading In[17], in expression starting on line 3",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"LoadError: MethodError: `convert` has no method matching convert(::Type{SubString{ASCIIString}}, ::Dict{Any,Any})\nThis may have arisen from a call to the constructor SubString{ASCIIString}(...),\nsince type constructors fall back to convert methods.\nClosest candidates are:\n call{T}(::Type{T}, ::Any)\n convert{T<:AbstractString}(::Type{T<:AbstractString}, !Matched::AbstractArray{Char,1})\n convert{T<:AbstractString}(::Type{SubString{T<:AbstractString}}, !Matched::T<:AbstractString)\n ...\nwhile loading In[17], in expression starting on line 3",
|
||
"",
|
||
" in setindex! at dict.jl:615",
|
||
" in parse_header at /Users/jukka/.julia/v0.4/JuliaFEM/src/abaqus_reader.jl:40",
|
||
" in parse_abaqus at /Users/jukka/.julia/v0.4/JuliaFEM/src/abaqus_reader.jl:120"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
" in depwarn at /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib\n",
|
||
" in beginswith at deprecated.jl:30\n",
|
||
" in parse_abaqus at /Users/jukka/.julia/v0.4/JuliaFEM/src/abaqus_reader.jl:115\n",
|
||
" in include_string at loading.jl:99\n",
|
||
" in execute_request_0x535c5df2 at /Users/jukka/.julia/v0.4/IJulia/src/execute_request.jl:157\n",
|
||
" in eventloop at /Users/jukka/.julia/v0.4/IJulia/src/IJulia.jl:123\n",
|
||
" in anonymous at task.jl:365\n",
|
||
"while loading In[17], in expression starting on line 3\n",
|
||
"WARNING: beginswith is deprecated, use startswith instead.\n",
|
||
" in depwarn at /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib\n",
|
||
" in beginswith at deprecated.jl:30\n",
|
||
" in parse_abaqus at /Users/jukka/.julia/v0.4/JuliaFEM/src/abaqus_reader.jl:115\n",
|
||
" in include_string at loading.jl:99\n",
|
||
" in execute_request_0x535c5df2 at /Users/jukka/.julia/v0.4/IJulia/src/execute_request.jl:157\n",
|
||
" in eventloop at /Users/jukka/.julia/v0.4/IJulia/src/IJulia.jl:123\n",
|
||
" in anonymous at task.jl:365\n",
|
||
"while loading In[17], in expression starting on line 3\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"using JuliaFEM.abaqus_reader\n",
|
||
"fid = open(\"../geometry/3d_beam/palkki.inp\")\n",
|
||
"model = JuliaFEM.abaqus_reader.parse_abaqus(fid)\n",
|
||
"close(fid)\n",
|
||
"model"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"scrolled": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"15-Aug 17:04:30:DEBUG:root:Creating elements\n",
|
||
"15-Aug 17:04:31:INFO:root:create_ldof2gdofmap: dofs per node: 3\n",
|
||
"15-Aug 17:04:31:INFO:root:solve!: dofs per node: 3\n",
|
||
"15-Aug 17:04:31:DEBUG:root:Problem size = 894\n",
|
||
"15-Aug 17:04:31:DEBUG:root:Starting iteration 1\n",
|
||
"15-Aug 17:04:31:DEBUG:root:Assembling\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Added 28 Lagrange multipliers to model\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Solving system of equations. Total size = 921\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Solution norm du = 72.87727091053921\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Starting iteration 2\n",
|
||
"15-Aug 17:04:36:DEBUG:root:Assembling\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Added 28 Lagrange multipliers to model\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Solving system of equations. Total size = 921\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Solution norm du = 2.737285770100854\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Starting iteration 3\n",
|
||
"15-Aug 17:04:40:DEBUG:root:Assembling\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Added 28 Lagrange multipliers to model\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Solving system of equations. Total size = 921\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Solution norm du = 0.07997112801214978\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Starting iteration 4\n",
|
||
"15-Aug 17:04:44:DEBUG:root:Assembling\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Added 28 Lagrange multipliers to model\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Solving system of equations. Total size = 921\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Solution norm du = 6.406557430235748e-5\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Starting iteration 5\n",
|
||
"15-Aug 17:04:48:DEBUG:root:Assembling\n",
|
||
"15-Aug 17:04:52:DEBUG:root:Adding Dirichlet boundary conditions using Lagrange multipliers\n",
|
||
"15-Aug 17:04:52:DEBUG:root:Added 28 Lagrange multipliers to model\n",
|
||
"15-Aug 17:04:52:DEBUG:root:Adding Neumann boundary conditions\n",
|
||
"15-Aug 17:04:52:DEBUG:root:Solving system of equations. Total size = 921\n",
|
||
"15-Aug 17:04:52:DEBUG:root:Solution norm du = 6.870072007793185e-11\n",
|
||
"15-Aug 17:04:52:DEBUG:root:Converged in 5 iterations.\n",
|
||
"15-Aug 17:04:52:INFO:root:Maximum absolute displacement in y direction: 6.9925206227884695\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"function solve_3d_model()\n",
|
||
" Logging.debug(\"Creating elements\")\n",
|
||
" elements = Element[]\n",
|
||
" coordinates = zeros(3, 10)\n",
|
||
" for (elid, node_ids) in model[\"elements\"]\n",
|
||
" for (i, nid) in enumerate(node_ids)\n",
|
||
" coordinates[:,i] = model[\"nodes\"][nid]\n",
|
||
" end\n",
|
||
" attributes = Dict(\"Young\" => 90, \"Poisson\" => 0.25)\n",
|
||
" el = Element(elid, node_ids, coordinates, attributes)\n",
|
||
" push!(elements, el)\n",
|
||
" end\n",
|
||
"\n",
|
||
" # create \"dofmap\" so that we know how to assemble global stiffness matrix\n",
|
||
" dofmap = create_ldof2gdofmap(elements; ndofs=3)\n",
|
||
"\n",
|
||
" # Boundary conditions\n",
|
||
"\n",
|
||
" # dirichlet bc, set dx=dy=dz for all nodes in set SUPPORT\n",
|
||
" bc_support = BC(Int64[], Float64[])\n",
|
||
" for nid in model[\"nsets\"][\"SUPPORT\"]\n",
|
||
" for i=1:3\n",
|
||
" push!(bc_support.dofs, dofmap[nid][i])\n",
|
||
" push!(bc_support.values, 0.0)\n",
|
||
" end\n",
|
||
" end\n",
|
||
"\n",
|
||
" # force boundary condition, put -1 to 2nd dof for each node in set LOAD\n",
|
||
" bc_load = BC(Int64[], Float64[])\n",
|
||
" for nid in model[\"nsets\"][\"LOAD\"]\n",
|
||
" push!(bc_load.dofs, dofmap[nid][2])\n",
|
||
" push!(bc_load.values, -30.0)\n",
|
||
" end\n",
|
||
"\n",
|
||
" #solve!(elements, [bc1], [bc2]; max_iterations=7)\n",
|
||
" neumann_bcs = [bc_load]\n",
|
||
" dirichlet_bcs = [bc_support]\n",
|
||
" # ndofs = dimension of unknown field in nodes\n",
|
||
" solve!(elements, dofmap, neumann_bcs, dirichlet_bcs; ndofs=3, max_iterations=10)\n",
|
||
"\n",
|
||
" # Let's pick maximum absolute displacement in y direction\n",
|
||
" maxdisp = 0.0\n",
|
||
" for el in elements\n",
|
||
" eldisp = el.attributes[\"displacement\"]\n",
|
||
" eldispy = eldisp[2,:]\n",
|
||
" maxeldisp = maximum(abs(eldispy))\n",
|
||
" if maxeldisp > maxdisp\n",
|
||
" maxdisp = maxeldisp\n",
|
||
" end\n",
|
||
" end\n",
|
||
" Logging.info(\"Maximum absolute displacement in y direction: $maxdisp\")\n",
|
||
" return model, elements, dofmap\n",
|
||
"end\n",
|
||
"\n",
|
||
"model, elements, dofmap = solve_3d_model();"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Saving results to file"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 15,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<Grid Name=\"Grid\">\n",
|
||
" <Time Value=\"0\"/>\n",
|
||
"</Grid>\n"
|
||
]
|
||
},
|
||
"execution_count": 15,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"xdoc, xmodel = JuliaFEM.xdmf.xdmf_new_model()\n",
|
||
"temporal_collection = JuliaFEM.xdmf.xdmf_new_temporal_collection(xmodel)\n",
|
||
"grid = JuliaFEM.xdmf.xdmf_new_grid(temporal_collection; time=0)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Save geometry to xdmf file"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"15-Aug 17:04:54:INFO:root:Number of nodes in model: 298\n",
|
||
"15-Aug 17:04:54:INFO:root:Number of elements in model: 120\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"nnodes = length(model[\"nodes\"])\n",
|
||
"Logging.info(\"Number of nodes in model: $nnodes\")\n",
|
||
"node_ids = Int64[]\n",
|
||
"for nid in keys(model[\"nodes\"])\n",
|
||
" push!(node_ids, nid)\n",
|
||
"end\n",
|
||
"sort!(node_ids)\n",
|
||
"X = zeros(3, nnodes)\n",
|
||
"for (i, nid) in enumerate(node_ids)\n",
|
||
" X[:,i] = model[\"nodes\"][nid]\n",
|
||
"end\n",
|
||
"\n",
|
||
"nelements = length(model[\"elements\"])\n",
|
||
"Logging.info(\"Number of elements in model: $nelements\")\n",
|
||
"elmap = zeros(Int64, 11, nelements)\n",
|
||
"elmap[1,:] = 0x0026\n",
|
||
"for elid in 1:nelements\n",
|
||
" elmap[2:end,elid] = model[\"elements\"][elid]\n",
|
||
"end"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"true"
|
||
]
|
||
},
|
||
"execution_count": 17,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"using LightXML\n",
|
||
"\n",
|
||
"function xdmf_new_mesh(grid, X, elmap)\n",
|
||
" dim, nnodes = size(X)\n",
|
||
" geometry = new_child(grid, \"Geometry\")\n",
|
||
" set_attribute(geometry, \"Type\", \"XYZ\")\n",
|
||
" dataitem = new_child(geometry, \"DataItem\")\n",
|
||
" set_attribute(dataitem, \"DataType\", \"Float\")\n",
|
||
" set_attribute(dataitem, \"Dimensions\", \"$nnodes $dim\")\n",
|
||
" set_attribute(dataitem, \"Format\", \"XML\")\n",
|
||
" set_attribute(dataitem, \"Precision\", 8)\n",
|
||
" #add_text(dataitem, join(X, \" \"))\n",
|
||
" s = \"\\n\"\n",
|
||
" \n",
|
||
" for i=1:nnodes\n",
|
||
" s *= \"\\t\\t\" * join(X[:,i], \" \") * \"\\n\"\n",
|
||
" end\n",
|
||
" s *= \" \"\n",
|
||
" add_text(dataitem, s)\n",
|
||
"\n",
|
||
" elmap2 = copy(elmap)\n",
|
||
" elmap2[2:end,:] -= 1\n",
|
||
" dim, nelements = size(elmap2)\n",
|
||
"\n",
|
||
" topology = new_child(grid, \"Topology\")\n",
|
||
" #set_attribute(topology, \"Dimensions\", \"1\")\n",
|
||
" set_attribute(topology, \"TopologyType\", \"Mixed\")\n",
|
||
" set_attribute(topology, \"NumberOfElements\", nelements)\n",
|
||
" dataitem = new_child(topology, \"DataItem\")\n",
|
||
" set_attribute(dataitem, \"DataType\", \"Int\")\n",
|
||
" set_attribute(dataitem, \"Dimensions\", \"$nelements $dim\")\n",
|
||
" set_attribute(dataitem, \"Format\", \"XML\")\n",
|
||
" set_attribute(dataitem, \"Precision\", 8)\n",
|
||
" s = \"\\n\"\n",
|
||
" for i=1:nelements\n",
|
||
" s *= \"\\t\\t\" * join(elmap2[:,i], \" \") * \"\\n\"\n",
|
||
" end\n",
|
||
" add_text(dataitem, s)\n",
|
||
" #add_text(dataitem, join(elmap2, \" \"))\n",
|
||
" \n",
|
||
"end\n",
|
||
"\n",
|
||
"xdmf_new_mesh(grid, X, elmap)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"10435"
|
||
]
|
||
},
|
||
"execution_count": 18,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"JuliaFEM.xdmf.xdmf_save_model(xdoc, \"/tmp/3d_solid_model.xmf\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Save nodal data to model"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 19,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"Dict{Any,Any} with 298 entries:\n",
|
||
" 288 => [-0.21784897897079505,-6.64256844921929,0.18339325827190953]\n",
|
||
" 11 => [-0.17342410820059667,-6.343125806991628,0.17544367431766225]\n",
|
||
" 158 => [-0.0007723334905839533,-0.2321904799732306,-0.03883691791045858]\n",
|
||
" 215 => [-0.03299227384130259,-4.2236276356937505,-0.0017757488281830807]\n",
|
||
" 134 => [-0.06336705102703495,-3.3332586850719337,0.06555932581531249]\n",
|
||
" 160 => [0.03205303832663507,-0.536361456950779,-0.07291283371223893]\n",
|
||
" 29 => [-0.01620524134284992,-0.19455583841608232,-0.03838421619811468]\n",
|
||
" 131 => [0.04015396763870081,-3.5101776818531523,0.10045744211179368]\n",
|
||
" 249 => [-0.2491004521409732,-6.570813533283954,0.06837890174506163]\n",
|
||
" 207 => [0.03974407267311282,-3.48588780058722,0.007971846403163977]\n",
|
||
" 173 => [-0.04472757590353555,-4.582185697159958,-0.04434348606400347]\n",
|
||
" 289 => [-0.16494613158592017,-6.360857515886982,0.33435404817411213]\n",
|
||
" 74 => [-0.03449870789750817,-3.947284664599636,0.0692691027146262]\n",
|
||
" 201 => [-0.00128347996939122,-3.8527236749372054,0.054216444201382656]\n",
|
||
" 176 => [-0.004729440266412542,-3.132546258410676,0.0036604388995965386]\n",
|
||
" 57 => [-0.021453552968802154,-4.134921994863808,0.04888988010136468]\n",
|
||
" 31 => [-0.005045439296021616,-0.3424143474221696,-0.0365148544462663]\n",
|
||
" 285 => [-0.19371941654927557,-6.446502168659889,0.18022053743770028]\n",
|
||
" 70 => [0.006277500845425116,-3.802694347992476,0.06251589929767469]\n",
|
||
" 33 => [-0.02778798411401373,-0.5091869603980016,0.03538255963543149]\n",
|
||
" 252 => [-0.11915625386204923,-1.2182594899567352,-0.025975085489623087]\n",
|
||
" 114 => [-0.14643901527350212,-0.4628626545501056,-0.0057156433415159625]\n",
|
||
" 165 => [-0.07462160313837857,-4.426674712264929,-0.04391022455570823]\n",
|
||
" 96 => [0.0541064545893336,-5.057801826440659,-0.01669155772495867]\n",
|
||
" 133 => [0.01615115174975327,-3.140610327091724,0.028951801068022566]\n",
|
||
" ⋮ => ⋮"
|
||
]
|
||
},
|
||
"execution_count": 19,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"nodaldisp = Dict()\n",
|
||
"for el in elements\n",
|
||
" for (i, nid) in enumerate(el.node_ids)\n",
|
||
" nodaldisp[nid] = el.attributes[\"displacement\"][:, i]\n",
|
||
" end\n",
|
||
"end\n",
|
||
"nodaldisp"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 20,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"3x298 Array{Float64,2}:\n",
|
||
" -0.202475 -0.17437 0.0131267 -0.0340868 -0.0252162 0.0521758 … -0.054781 -0.169903 0.186936 0.102666 -0.0970747 -0.164397 0.0\n",
|
||
" -1.34204 -1.66404 -3.20587 -3.27673 -3.68732 -3.36789 -4.33822 -1.03943 -2.27466 -1.67467 -2.91213 -2.52353 0.0\n",
|
||
" 0.0211856 0.0324162 0.00213878 0.0377156 0.0683502 0.030081 -0.00684333 -0.035509 0.304867 0.26033 0.113802 0.152433 0.0"
|
||
]
|
||
},
|
||
"execution_count": 20,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"u = zeros(3, nnodes)\n",
|
||
"for (i, nid) in enumerate(node_ids)\n",
|
||
" u[:,i] = nodaldisp[nid]\n",
|
||
"end\n",
|
||
"u"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 21,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"true"
|
||
]
|
||
},
|
||
"execution_count": 21,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"JuliaFEM.xdmf.xdmf_new_field(grid, \"Displacement\", \"nodes\", u)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 22,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"28330"
|
||
]
|
||
},
|
||
"execution_count": 22,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"JuliaFEM.xdmf.xdmf_save_model(xdoc, \"/tmp/3d_solid_model.xmf\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"([0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0,0.0])"
|
||
]
|
||
},
|
||
"execution_count": 17,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"u = zeros(10)\n",
|
||
"u1 = u[1:5]\n",
|
||
"u, u1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"metadata": {
|
||
"collapsed": false
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"([0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],[1.0,1.0,1.0,1.0,1.0])"
|
||
]
|
||
},
|
||
"execution_count": 18,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"u1[:] = 1\n",
|
||
"u, u1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": true
|
||
},
|
||
"outputs": [],
|
||
"source": []
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Julia 0.4.0-dev",
|
||
"language": "julia",
|
||
"name": "julia-0.4"
|
||
},
|
||
"language_info": {
|
||
"name": "julia",
|
||
"version": "0.4.0"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 0
|
||
}
|