From bba9d380fbd2a94d65378e5a7a69d5db9e2132e2 Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Wed, 23 Dec 2015 01:52:28 +0200 Subject: [PATCH] more general way to define saddle point problem. --- notebooks/2015-11-23-2d-tie-contact.ipynb | 618 ++++++++++++++++-- ...-12-18-normal-tangential-coordinates.ipynb | 253 +++---- src/assembly.jl | 32 +- src/directsolver.jl | 47 +- src/dirichlet.jl | 13 +- src/elasticity.jl | 3 + src/equations.jl | 40 +- src/mortar.jl | 31 +- src/problems.jl | 6 +- src/sparse.jl | 17 +- src/test.jl | 7 +- src/xdmf.jl | 1 + test/test_mortar.jl | 351 +--------- test/test_mortar_2d.jl | 355 ++++++++++ 14 files changed, 1115 insertions(+), 659 deletions(-) create mode 100644 test/test_mortar_2d.jl diff --git a/notebooks/2015-11-23-2d-tie-contact.ipynb b/notebooks/2015-11-23-2d-tie-contact.ipynb index e78eebc..dc957db 100644 --- a/notebooks/2015-11-23-2d-tie-contact.ipynb +++ b/notebooks/2015-11-23-2d-tie-contact.ipynb @@ -4,13 +4,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 2d tie contact\n", + "# 2d contacts\n", "\n", "Author: Jukka Aho\n", "\n", "Abstract: 2d tie contact.\n", "\n", - "Model:\n", + "## Model 1: three body tie contact\n", "\n", "\n", "![model](http://s4.postimg.org/u9yqeryul/Screenshot_from_2015_11_24_02_00_00.png)\n", @@ -31,36 +31,30 @@ }, "outputs": [], "source": [ - "using JuliaFEM\n", - "using JuliaFEM: Element, Seg2, Quad4, PlaneStressElasticityProblem, DirichletProblem, MortarProblem, DirectSolver" + "using JuliaFEM.Core: Element, Seg2, Quad4, PlaneStressElasticityProblem,\n", + " DirichletProblem, MortarProblem, DirectSolver" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [], "source": [ "nodes = Dict{Int64, Vector{Float64}}(\n", - " 1 => [0.0, 0.0],\n", - " 2 => [2.0, 0.0],\n", - " 3 => [2.0, 1.0],\n", - " 4 => [0.0, 1.0],\n", - " 5 => [0.0, 1.0],\n", - " 6 => [1.0, 1.0],\n", - " 7 => [1.0, 2.0],\n", - " 8 => [0.0, 2.0],\n", - " 9 => [1.0, 1.0],\n", - " 10 => [2.0, 1.0],\n", - " 11 => [2.0, 2.0],\n", - " 12 => [1.0, 2.0]);" + " 1 => [0.0, 0.0], 2 => [2.0, 0.0],\n", + " 3 => [2.0, 1.0], 4 => [0.0, 1.0],\n", + " 5 => [0.0, 1.0], 6 => [1.0, 1.0],\n", + " 7 => [1.0, 2.0], 8 => [0.0, 2.0],\n", + " 9 => [1.0, 1.0], 10 => [2.0, 1.0],\n", + " 11 => [2.0, 2.0], 12 => [1.0, 2.0]);" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 11, "metadata": { "collapsed": true }, @@ -74,20 +68,17 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: number of elements: 3\n" + ] } ], "source": [ @@ -99,7 +90,8 @@ " element[\"poissons ratio\"] = 0.25\n", " push!(elements, element)\n", "end\n", - "length(elements)" + "nelements = length(elements)\n", + "info(\"number of elements: $nelements\")" ] }, { @@ -111,15 +103,15 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "body1 = PlaneStressElasticityProblem()\n", - "body2 = PlaneStressElasticityProblem()\n", - "body3 = PlaneStressElasticityProblem()\n", + "body1 = PlaneStressElasticityProblem(\"body 1\")\n", + "body2 = PlaneStressElasticityProblem(\"body 2\")\n", + "body3 = PlaneStressElasticityProblem(\"body 3\")\n", "push!(body1, elements[1])\n", "push!(body2, elements[2])\n", "push!(body3, elements[3]);" @@ -134,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 15, "metadata": { "collapsed": false }, @@ -159,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 16, "metadata": { "collapsed": false }, @@ -185,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 17, "metadata": { "collapsed": false }, @@ -207,20 +199,23 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)]\n", + "#rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)]\n", + "using JuliaFEM.Core: calculate_normal_tangential_coordinates!\n", "\n", "master1 = Seg2([4, 3])\n", "master1[\"geometry\"] = Vector[nodes[4], nodes[3]]\n", "slave1 = Seg2([5, 6])\n", "slave1[\"geometry\"] = Vector[nodes[5], nodes[6]]\n", "slave1[\"master elements\"] = Element[master1]\n", - "slave1[\"nodal ntsys\"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)]\n", + "calculate_normal_tangential_coordinates!(slave1, 0.0)\n", + "\n", + "#slave1[\"nodal ntsys\"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)]\n", "contact1 = MortarProblem(\"displacement\", 2)\n", "push!(contact1, slave1);" ] @@ -234,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 20, "metadata": { "collapsed": false }, @@ -242,8 +237,9 @@ "source": [ "slave2 = Seg2([9, 10])\n", "slave2[\"geometry\"] = Vector[nodes[9], nodes[10]]\n", - "slave2[\"nodal ntsys\"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)]\n", + "#slave2[\"nodal ntsys\"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)]\n", "slave2[\"master elements\"] = Element[master1]\n", + "calculate_normal_tangential_coordinates!(slave2, 0.0)\n", "contact2 = MortarProblem(\"displacement\", 2)\n", "push!(contact2, slave2);" ] @@ -257,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 21, "metadata": { "collapsed": true }, @@ -267,7 +263,8 @@ "master2[\"geometry\"] = Vector[nodes[6], nodes[7]]\n", "slave3 = Seg2([9, 12])\n", "slave3[\"geometry\"] = Vector[nodes[9], nodes[12]]\n", - "slave3[\"nodal ntsys\"] = Matrix[rotation_matrix(0.0), rotation_matrix(0.0)]\n", + "#slave3[\"nodal ntsys\"] = Matrix[rotation_matrix(0.0), rotation_matrix(0.0)]\n", + "calculate_normal_tangential_coordinates!(slave3, 0.0)\n", "slave3[\"master elements\"] = Element[master2]\n", "contact3 = MortarProblem(\"displacement\", 2)\n", "push!(contact3, slave3);" @@ -282,7 +279,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 22, "metadata": { "collapsed": false }, @@ -301,7 +298,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 23, "metadata": { "collapsed": false }, @@ -310,12 +307,108 @@ "name": "stderr", "output_type": "stream", "text": [ + "INFO: Starting solver DirectSolver\n", "INFO: # of field problems: 3\n", "INFO: # of boundary problems: 5\n", "INFO: Starting iteration 1\n", - "INFO: # of dofs: 24, # of interface dofs: 15\n", - "INFO: solved. length of solution vector = 48\n", - "INFO: Iteration took 9.311098465 seconds\n" + "INFO: Assembling field problems...\n", + "INFO: Assembling body 1: body 1\n", + "INFO: Assembling body 2: body 2\n", + "INFO: Assembling body 3: body 3\n", + "INFO: dim = 24\n", + "INFO: Assembling boundary problems...\n", + "INFO: Assembling boundary 1: dirichlet boundary\n", + "INFO: Assembling boundary 2: dirichlet boundary\n", + "INFO: Assembling boundary 3: mortar problem\n", + "INFO: Assembling boundary 4: mortar problem\n", + "INFO: Assembling boundary 5: mortar problem\n", + "INFO: Solving system\n", + "INFO: UMFPACK: solved in 0.3197059631347656 seconds. norm = 0.5357583756107197\n", + "INFO: timing info for iteration:\n", + "INFO: boundary assembly : 0.3747282028198242\n", + "INFO: field assembly : 2.646785020828247\n", + "INFO: dump matrices to disk : 9.5367431640625e-7\n", + "INFO: solve problem : 0.4615659713745117\n", + "INFO: update element data : 0.02040410041809082\n", + "INFO: non-linear iteration : 3.5035040378570557\n", + "INFO: Starting iteration 2\n", + "INFO: Assembling field problems...\n", + "INFO: Assembling body 1: body 1\n", + "INFO: Assembling body 2: body 2\n", + "INFO: Assembling body 3: body 3\n", + "INFO: dim = 24\n", + "INFO: Assembling boundary problems...\n", + "INFO: Assembling boundary 1: dirichlet boundary\n", + "INFO: Assembling boundary 2: dirichlet boundary\n", + "INFO: Assembling boundary 3: mortar problem\n", + "INFO: Assembling boundary 4: mortar problem\n", + "INFO: Assembling boundary 5: mortar problem\n", + "INFO: Solving system\n", + "INFO: UMFPACK: solved in 0.0003139972686767578 seconds. norm = 0.12311066326855769\n", + "INFO: timing info for iteration:\n", + "INFO: boundary assembly : 0.036119937896728516\n", + "INFO: field assembly : 0.0374150276184082\n", + "INFO: dump matrices to disk : 9.5367431640625e-7\n", + "INFO: solve problem : 0.06756091117858887\n", + "INFO: update element data : 0.00013899803161621094\n", + "INFO: non-linear iteration : 0.1412510871887207\n", + "INFO: Starting iteration 3\n", + "INFO: Assembling field problems...\n", + "INFO: Assembling body 1: body 1\n", + "INFO: Assembling body 2: body 2\n", + "INFO: Assembling body 3: body 3\n", + "INFO: dim = 24\n", + "INFO: Assembling boundary problems...\n", + "INFO: Assembling boundary 1: dirichlet boundary\n", + "INFO: Assembling boundary 2: dirichlet boundary\n", + "INFO: Assembling boundary 3: mortar problem\n", + "INFO: Assembling boundary 4: mortar problem\n", + "INFO: Assembling boundary 5: mortar problem\n", + "INFO: Solving system\n", + "INFO: UMFPACK: solved in 0.0003230571746826172 seconds. norm = 0.006976385449837204\n", + "INFO: timing info for iteration:\n", + "INFO: boundary assembly : 0.03788185119628906\n", + "INFO: field assembly : 0.036910057067871094\n", + "INFO: dump matrices to disk : 0.0\n", + "INFO: solve problem : 0.07133316993713379\n", + "INFO: update element data : 0.0001468658447265625\n", + "INFO: non-linear iteration : 0.1462879180908203\n", + "INFO: Starting iteration 4\n", + "INFO: Assembling field problems...\n", + "INFO: Assembling body 1: body 1\n", + "INFO: Assembling body 2: body 2\n", + "INFO: Assembling body 3: body 3\n", + "INFO: dim = 24\n", + "INFO: Assembling boundary problems...\n", + "INFO: Assembling boundary 1: dirichlet boundary\n", + "INFO: Assembling boundary 2: dirichlet boundary\n", + "INFO: Assembling boundary 3: mortar problem\n", + "INFO: Assembling boundary 4: mortar problem\n", + "INFO: Assembling boundary 5: mortar problem\n", + "INFO: Solving system\n", + "INFO: UMFPACK: solved in 0.00030493736267089844 seconds. norm = 2.1945519744339283e-5\n", + "INFO: timing info for iteration:\n", + "INFO: boundary assembly : 0.037918806076049805\n", + "INFO: field assembly : 0.036936044692993164\n", + "INFO: dump matrices to disk : 9.5367431640625e-7\n", + "INFO: solve problem : 0.07027888298034668\n", + "INFO: update element data : 0.00013899803161621094\n", + "INFO: non-linear iteration : 0.14528894424438477\n", + "INFO: Starting iteration 5\n", + "INFO: Assembling field problems...\n", + "INFO: Assembling body 1: body 1\n", + "INFO: Assembling body 2: body 2\n", + "INFO: Assembling body 3: body 3\n", + "INFO: dim = 24\n", + "INFO: Assembling boundary problems...\n", + "INFO: Assembling boundary 1: dirichlet boundary\n", + "INFO: Assembling boundary 2: dirichlet boundary\n", + "INFO: Assembling boundary 3: mortar problem\n", + "INFO: Assembling boundary 4: mortar problem\n", + "INFO: Assembling boundary 5: mortar problem\n", + "INFO: Solving system\n", + "INFO: UMFPACK: solved in 0.0003120899200439453 seconds. norm = 2.172141514107444e-10\n", + "INFO: timing info for iteration:\n" ] }, { @@ -324,7 +417,7 @@ "(5,true)" ] }, - "execution_count": 13, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, @@ -332,22 +425,13 @@ "name": "stderr", "output_type": "stream", "text": [ - "INFO: Starting iteration 2\n", - "INFO: # of dofs: 24, # of interface dofs: 15\n", - "INFO: solved. length of solution vector = 48\n", - "INFO: Iteration took 0.003787437 seconds\n", - "INFO: Starting iteration 3\n", - "INFO: # of dofs: 24, # of interface dofs: 15\n", - "INFO: solved. length of solution vector = 48\n", - "INFO: Iteration took 0.020931551 seconds\n", - "INFO: Starting iteration 4\n", - "INFO: # of dofs: 24, # of interface dofs: 15\n", - "INFO: solved. length of solution vector = 48\n", - "INFO: Iteration took 0.003763852 seconds\n", - "INFO: Starting iteration 5\n", - "INFO: # of dofs: 24, # of interface dofs: 15\n", - "INFO: solved. length of solution vector = 48\n", - "INFO: Iteration took 0.003679408 seconds\n" + "INFO: boundary assembly : 0.035440921783447266\n", + "INFO: field assembly : 0.0363919734954834\n", + "INFO: dump matrices to disk : 0.0\n", + "INFO: solve problem : 0.06740903854370117\n", + "INFO: update element data : 0.0001380443572998047\n", + "INFO: non-linear iteration : 0.13939404487609863\n", + "INFO: solver finished in 4.193101167678833 seconds.\n" ] } ], @@ -357,7 +441,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 24, "metadata": { "collapsed": false }, @@ -366,8 +450,19 @@ "name": "stderr", "output_type": "stream", "text": [ - "INFO: displacement at [2.0,2.0] = [0.06348623177789343,-0.27718303785565257]\n" + "INFO: displacement at [2.0,2.0] = [0.06348623177789363,-0.2771830378556528]\n" ] + }, + { + "data": { + "text/plain": [ + "Test Passed\n", + " Expression: isapprox(u,[0.0634862,-0.277183],atol=1.0e-5)" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -380,11 +475,398 @@ "info(\"displacement at $X = $u\")\n", "@test isapprox(u, [0.0634862, -0.277183], atol=1.0e-5)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model 2: splitted beam, tie contact\n", + "\n", + "\n", + "\n", + "Put some load to the top, dx=dy=0 on left boundary." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "using JuliaFEM.Preprocess: parse_aster_med_file\n", + "using JuliaFEM.Core: PlaneStressLinearElasticityProblem, DirichletProblem,\n", + " get_connectivity, Quad4, Tri3, Seg2, LinearSolver,\n", + " update!, get_elements" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: Found 5 element sets: LOWER_TO_UPPER, RIGHT, UPPER_TO_LOWER, LEFT, LOAD\n" + ] + }, + { + "data": { + "text/plain": [ + "Dict{ASCIIString,Any} with 2 entries:\n", + " \"nodes\" => Dict(68=>[71.42857142857142,9.999999999999998],2=>[95.0,-4.…\n", + " \"connectivity\" => Dict(11=>(:SE2,:OTHER,[11,12]),134=>(:TR3,:OTHER,[75,96,76]…" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mesh = parse_aster_med_file(Pkg.dir(\"JuliaFEM\")*\"/geometry/2d_beam/BEAM.med\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: created 104 field elements.\n", + "INFO: created 4 boundary elements.\n" + ] + } + ], + "source": [ + "field_problem = PlaneStressLinearElasticityProblem()\n", + "\n", + "# field problems\n", + "joo = Dict(:QU4 => Quad4, :TR3 => Tri3)\n", + "for (elid, (eltype, elset, elcon)) in mesh[\"connectivity\"]\n", + " eltype in keys(joo) || continue\n", + " element = joo[eltype](elcon)\n", + " update!(element, \"geometry\", mesh[\"nodes\"])\n", + " element[\"youngs modulus\"] = 900.0\n", + " element[\"poissons ratio\"] = 0.25\n", + " push!(field_problem, element)\n", + "end\n", + "\n", + "# neumann boundary condition -1 on y direction\n", + "for (elid, (eltype, elset, elcon)) in mesh[\"connectivity\"]\n", + " eltype == :SE2 || continue\n", + " elset == :LOAD || continue\n", + " element = Seg2(elcon)\n", + " update!(element, \"geometry\", mesh[\"nodes\"])\n", + " element[\"displacement traction force 2\"] = -1.0\n", + " push!(field_problem, element)\n", + "end\n", + "\n", + "# boundary conditions\n", + "boundary_problem = DirichletProblem(\"displacement\", 2)\n", + "\n", + "for (elid, (eltype, elset, elcon)) in mesh[\"connectivity\"]\n", + " eltype == :SE2 || continue\n", + " elset == :LEFT || continue\n", + " element = Seg2(elcon)\n", + " update!(element, \"geometry\", mesh[\"nodes\"])\n", + " element[\"displacement\"] = 0.0\n", + " push!(boundary_problem, element)\n", + "end\n", + "\n", + "info(\"created $(length(get_elements(field_problem))) field elements.\")\n", + "info(\"created $(length(get_elements(boundary_problem))) boundary elements.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Contact definition: contact pair is `LOWER_TO_UPPER <--> UPPER_TO_LOWER`:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: # of master elements: 14\n", + "INFO: # of slave elements: 20\n" + ] + } + ], + "source": [ + "using JuliaFEM.Core: Element, MortarProblem, calculate_normal_tangential_coordinates!\n", + "\n", + "mortar_surface = :UPPER_TO_LOWER\n", + "slave_surface = :LOWER_TO_UPPER\n", + "\n", + "master_elements = JuliaFEM.Core.Element[]\n", + "for (elid, (eltype, elset, elcon)) in mesh[\"connectivity\"]\n", + " eltype == :SE2 || continue\n", + " elset == mortar_surface || continue\n", + " element = Seg2(elcon)\n", + " update!(element, \"geometry\", mesh[\"nodes\"])\n", + " push!(master_elements, element)\n", + "end\n", + "\n", + "contact_problem = MortarProblem(\"displacement\", 2)\n", + "for (elid, (eltype, elset, elcon)) in mesh[\"connectivity\"]\n", + " eltype == :SE2 || continue\n", + " elset == slave_surface || continue\n", + " element = Seg2(elcon)\n", + " update!(element, \"geometry\", mesh[\"nodes\"])\n", + " element[\"master elements\"] = master_elements\n", + " calculate_normal_tangential_coordinates!(element, 0.0)\n", + " push!(contact_problem, element)\n", + "end\n", + "\n", + "info(\"# of master elements: $(length(master_elements))\")\n", + "info(\"# of slave elements: $(length(contact_problem.elements))\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: Starting solver divided_beam\n", + "INFO: # of field problems: 1\n", + "INFO: # of boundary problems: 2\n", + "INFO: Starting iteration 1\n", + "INFO: Assembling field problems...\n", + "INFO: Assembling body 1: plane stress linear elasticity\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: dim = 210\n", + "INFO: Assembling boundary problems...\n", + "INFO: Assembling boundary 1: dirichlet boundary\n", + "INFO: Assembling boundary 2: mortar problem\n", + "INFO: Solving system\n", + "INFO: UMFPACK: solved in 0.0015990734100341797 seconds. norm = 104.93886213441557\n" + ] + }, + { + "data": { + "text/plain": [ + "(1,true)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: timing info for iteration:\n", + "INFO: boundary assembly : 0.09911894798278809\n", + "INFO: field assembly : 0.05243706703186035\n", + "INFO: dump matrices to disk : 9.5367431640625e-7\n", + "INFO: solve problem : 0.07156205177307129\n", + "INFO: update element data : 0.0012559890747070312\n", + "INFO: non-linear iteration : 0.2243940830230713\n", + "INFO: solver finished in 0.22567105293273926 seconds.\n" + ] + } + ], + "source": [ + "using JuliaFEM.Core: DirectSolver\n", + "solver = DirectSolver()\n", + "solver.name = \"divided_beam\"\n", + "solver.method = :UMFPACK\n", + "solver.nonlinear_problem = false\n", + "solver.max_iterations = 1\n", + "solver.dump_matrices = false\n", + "push!(solver, field_problem)\n", + "push!(solver, boundary_problem)\n", + "push!(solver, contact_problem)\n", + "call(solver, 0.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: XDFM: ndim = 210\n" + ] + } + ], + "source": [ + "xdoc, xmodel = JuliaFEM.Postprocess.xdmf_new_model()\n", + "coll = JuliaFEM.Postprocess.xdmf_new_temporal_collection(xmodel)\n", + "grid = JuliaFEM.Postprocess.xdmf_new_grid(coll; time=0.0)\n", + "\n", + "Xg = Dict{Int64, Vector{Float64}}()\n", + "ug = Dict{Int64, Vector{Float64}}()\n", + "for element in field_problem.elements\n", + " conn = get_connectivity(element)\n", + " X = element(\"geometry\", 0.0)\n", + " u = element(\"displacement\", 0.0)\n", + " for (i, c) in enumerate(conn)\n", + " Xg[c] = X[i]\n", + " ug[c] = u[i]\n", + " end\n", + "end\n", + "perm = sort(collect(keys(Xg)))\n", + "nodes = Vector{Float64}[Xg[i] for i in perm]\n", + "disp = Vector{Float64}[ug[i] for i in perm]\n", + "elements = []\n", + "\n", + "for el in field_problem.elements\n", + " isa(el, Element{Quad4}) || continue\n", + " push!(elements, (:Quad4, get_connectivity(el)))\n", + "end\n", + "for el in field_problem.elements\n", + " isa(el, Element{Tri3}) || continue\n", + " push!(elements, (:Tri3, get_connectivity(el)))\n", + "end\n", + "\n", + "#elements\n", + "JuliaFEM.Postprocess.xdmf_new_mesh!(grid, nodes, elements)\n", + "JuliaFEM.Postprocess.xdmf_new_nodal_field!(grid, \"displacement\", disp)\n", + "JuliaFEM.Postprocess.xdmf_save_model(xdoc, \"/tmp/beam_2d.xmf\");" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: using PyPlot.mesh in module Main conflicts with an existing identifier.\n", + "WARNING: using PyPlot.grid in module Main conflicts with an existing identifier.\n" + ] + } + ], + "source": [ + "using PyPlot" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "PyPlot.Figure(PyObject )" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(-20.0,120.0,-20.0,25.0)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig = figure(figsize=(15, 4))\n", + "for element in field_problem.elements\n", + " conn = get_connectivity(element)\n", + " X = element(\"geometry\", 0.0)\n", + " #info(X)\n", + " for i=1:length(X)\n", + " px1 = X[i][1]\n", + " py1 = X[i][2]\n", + " px2 = X[mod(i,length(X))+1][1]\n", + " py2 = X[mod(i,length(X))+1][2]\n", + " plot([px1, px2], [py1, py2], \"k-\")\n", + " end\n", + "end\n", + "for element in field_problem.elements\n", + " conn = get_connectivity(element)\n", + " X = element(\"geometry\", 0.0)\n", + " u = element(\"displacement\", 0.0)\n", + " x = X + u\n", + " #info(X)\n", + " for i=1:length(x)\n", + " px1 = x[i][1]\n", + " py1 = x[i][2]\n", + " px2 = x[mod(i,length(x))+1][1]\n", + " py2 = x[mod(i,length(x))+1][2]\n", + " plot([px1, px2], [py1, py2], \"r--\", alpha=0.5)\n", + " end\n", + "end\n", + "\n", + "axis(\"equal\")\n", + "axis(\"off\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model 3: splitted beam, frictionless contact, small sliding" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Julia 0.4.1", + "display_name": "Julia 0.4.2", "language": "julia", "name": "julia-0.4" }, @@ -392,7 +874,7 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "0.4.1" + "version": "0.4.2" } }, "nbformat": 4, diff --git a/notebooks/2015-12-18-normal-tangential-coordinates.ipynb b/notebooks/2015-12-18-normal-tangential-coordinates.ipynb index fe2fb82..c307adc 100644 --- a/notebooks/2015-12-18-normal-tangential-coordinates.ipynb +++ b/notebooks/2015-12-18-normal-tangential-coordinates.ipynb @@ -2457,7 +2457,7 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": 84, "metadata": { "collapsed": false }, @@ -2468,7 +2468,7 @@ "false" ] }, - "execution_count": 76, + "execution_count": 84, "metadata": {}, "output_type": "execute_result" } @@ -2479,9 +2479,8 @@ "using JuliaFEM.Core: calculate_normal_tangential_coordinates!\n", "\n", "# 2d rotation matrix\n", - "#ϕ = -pi/4\n", - "phi = pi/10\n", - "#phi = 0.0\n", + "#phi = pi/10\n", + "phi = 0.0\n", "rmat(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)]\n", "\n", "geometry = Dict{Int64, Node}(\n", @@ -2498,11 +2497,14 @@ "\n", "el1[\"youngs modulus\"] = 900.0\n", "el1[\"poissons ratio\"] = 0.25\n", - "# traction force in normal direction, (i.e. pressure load)\n", - "el2[\"displacement traction force N\"] = 100.0\n", - "# support sides in normal direction\n", - "el3[\"displacement 2\"] = 0.0\n", - "el4[\"displacement 1\"] = 0.0\n", + "# traction force in local coordinates\n", + "el2[\"local displacement traction force 1\"] = 100.0\n", + "# support sides in local coordinates\n", + "el3[\"local displacement 1\"] = 0.0\n", + "el4[\"local displacement 2\"] = 0.0\n", + "for el in [el3, el4]\n", + " el[\"displacement near coord (0.0,0.0)\"] = 0.0\n", + "end\n", "problem = PlaneStressLinearElasticityProblem(\"block\")\n", "boundary = DirichletProblem(\"dirichlet boundary conditions\", \"displacement\", 2)\n", "push!(problem, el1, el2)\n", @@ -2517,7 +2519,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": 85, "metadata": { "collapsed": false }, @@ -2525,14 +2527,12 @@ { "data": { "text/plain": [ - "8x1 sparse matrix with 4 Float64 entries:\n", - "\t[5, 1] = 15.4508\n", - "\t[6, 1] = -47.5528\n", - "\t[7, 1] = 15.4508\n", - "\t[8, 1] = -47.5528" + "8x1 sparse matrix with 2 Float64 entries:\n", + "\t[6, 1] = -50.0\n", + "\t[8, 1] = -50.0" ] }, - "execution_count": 77, + "execution_count": 85, "metadata": {}, "output_type": "execute_result" } @@ -2542,109 +2542,6 @@ "f = sparse(JuliaFEM.Core.assemble(problem, 0.0).force_vector)" ] }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "B\n", - "Array(Float64,(8,8)) 8x8 Array{Float64,2}:\n", - " 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0\n", - "C\n", - "Array(Float64,(8,8)) 8x8 Array{Float64,2}:\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - "D\n", - "Array(Float64,(8,8)) 8x8 Array{Float64,2}:\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n" - ] - } - ], - "source": [ - "# biorthogonal version\n", - "m = [1 0; 0 1]\n", - "#m = 1/6*[2 1; 1 2]\n", - "\n", - "\n", - "B = spzeros(8, 8)\n", - "C = spzeros(8, 8)\n", - "D = spzeros(8, 8)\n", - "\n", - "B[[1,3],[1,3]] += m\n", - "B[[2,4],[2,4]] += m\n", - "\n", - "B[[1,7],[1,7]] += m\n", - "B[[2,8],[2,8]] += m\n", - "\n", - "B[[3,5],[3,5]] += m\n", - "B[[4,6],[4,6]] += m\n", - "\n", - "B[[7,5],[7,5]] += m\n", - "B[[8,6],[8,6]] += m\n", - "\n", - "# version 1\n", - "\n", - "tangents = Vector{Float64}[\n", - " rmat(phi)*[1.0, 0.0],\n", - " rmat(phi)*[1.0, 0.0],\n", - " rmat(phi)*[0.0, 1.0],\n", - " rmat(phi)*[0.0, 1.0]]\n", - "\n", - "normals = Vector{Float64}[rot(pi/2)*t for t in tangents]\n", - "\n", - "#=\n", - "# fixed in every direction\n", - "C[1, [1,2]] = normals[1]\n", - "C[2, [1,2]] = tangents[1]\n", - "#C[1,1] = 1.0\n", - "#C[2,2] = 1.0\n", - "# normal fixed, tangential free\n", - "C[3, [3,4]] = normals[2]\n", - "D[4, [3,4]] = tangents[2]\n", - "# allowed to move in n and t directions (inactive)\n", - "D[5, [5,6]] = normals[3]\n", - "D[6, [5,6]] = tangents[3]\n", - "#D[5,5] = 1.0\n", - "#D[6,6] = 1.0\n", - "# normal fixed, tangential free\n", - "C[7, [7,8]] = normals[4]\n", - "D[8, [7,8]] = tangents[4]\n", - "=#\n", - "\n", - "println(\"B\")\n", - "dump(round(full(B), 3))\n", - "println(\"C\")\n", - "dump(round(full(C), 3))\n", - "println(\"D\")\n", - "dump(round(full(D), 3))" - ] - }, { "cell_type": "code", "execution_count": 21, @@ -2693,7 +2590,7 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 86, "metadata": { "collapsed": false }, @@ -2702,10 +2599,10 @@ "name": "stderr", "output_type": "stream", "text": [ - "INFO: De = [0.49999999999999994 0.0\n", - " 0.0 0.49999999999999994]\n", - "INFO: De = [0.49999999999999994 0.0\n", - " 0.0 0.49999999999999994]\n" + "INFO: De = [0.5 0.0\n", + " 0.0 0.5]\n", + "INFO: De = [0.5 0.0\n", + " 0.0 0.5]\n" ] }, { @@ -2719,10 +2616,10 @@ "name": "stderr", "output_type": "stream", "text": [ - "INFO: De = [0.49999999999999994 0.0\n", - " 0.0 0.49999999999999994]\n", - "INFO: De = [0.49999999999999994 0.0\n", - " 0.0 0.49999999999999994]\n" + "INFO: De = [0.5 0.0\n", + " 0.0 0.5]\n", + "INFO: De = [0.5 0.0\n", + " 0.0 0.5]\n" ] }, { @@ -2739,22 +2636,22 @@ " 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0\n", " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0\n", "Array(Float64,(7,8)) 7x8 Array{Float64,2}:\n", - " 1.28 2.52 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 -0.62 1.9 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 1.9 0.62\n", + " 2.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0\n", "Array(Float64,(8,8)) 8x8 Array{Float64,2}:\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 2.52 -1.28 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 1.9 0.62 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.62 -1.9\n" + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 2.0 -2.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -2.0\n" ] } ], @@ -2953,7 +2850,7 @@ }, { "cell_type": "code", - "execution_count": 79, + "execution_count": 119, "metadata": { "collapsed": false }, @@ -2962,25 +2859,25 @@ "data": { "text/plain": [ "16x16 Array{Float64,2}:\n", - " 351.832 121.353 -231.353 -118.168 -131.832 -121.353 11.3525 118.168 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 121.353 528.168 -58.1678 11.3525 -121.353 -308.168 58.1678 -231.353 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " -231.353 -58.1678 528.168 -121.353 11.3525 58.1678 -308.168 121.353 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 \n", - " -118.168 11.3525 -121.353 351.832 118.168 -231.353 121.353 -131.832 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 \n", - " -131.832 -121.353 11.3525 118.168 351.832 121.353 -231.353 -118.168 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " -121.353 -308.168 58.1678 -231.353 121.353 528.168 -58.1678 11.3525 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 11.3525 58.1678 -308.168 121.353 -231.353 -58.1678 528.168 -121.353 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 \n", - " 118.168 -231.353 121.353 -131.832 -118.168 11.3525 -121.353 351.832 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - " 1.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.0 \n", - " 0.0 1.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 \n", - " 0.0 0.0 -0.618034 1.90211 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.90211 0.618034 0.0 0.0 0.0 0.0 \n", - " 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 0.0 \n", - " 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 0.0 \n", - " 0.0 0.0 0.0 0.0 0.0 0.0 1.90211 0.618034 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", - " 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.618034 -1.90211" + " 440.0 150.0 -260.0 -30.0 -220.0 -150.0 40.0 30.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 150.0 440.0 30.0 40.0 -150.0 -220.0 -30.0 -260.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " -260.0 30.0 440.0 -150.0 40.0 -30.0 -220.0 150.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0\n", + " -30.0 40.0 -150.0 440.0 30.0 -260.0 150.0 -220.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0\n", + " -220.0 -150.0 40.0 30.0 440.0 150.0 -260.0 -30.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " -150.0 -220.0 -30.0 -260.0 150.0 440.0 30.0 40.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 40.0 -30.0 -220.0 150.0 -260.0 30.0 440.0 -150.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0\n", + " 30.0 -260.0 150.0 -220.0 -30.0 40.0 -150.0 440.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0\n", + " 1.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.0\n", + " 0.0 1.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\n", + " 0.0 0.0 0.0 2.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\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0\n", + " 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 0.0\n", + " 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 0.0\n", + " 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n", + " 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 -2.0" ] }, - "execution_count": 79, + "execution_count": 119, "metadata": {}, "output_type": "execute_result" } @@ -2989,17 +2886,24 @@ "C1 = sparse(ntass.C1, 8, 8)\n", "C2 = sparse(ntass.C2, 8, 8)\n", "D = sparse(ntass.D, 8, 8)\n", + "C2[1,:] = 0\n", + "D[2,:] = 0\n", + "C2[1,1] = 1\n", + "C2[2,2] = 1\n", + "#C2[2,:] = D[2,:]\n", + "#D[2,:] = 0\n", "A = [K C1'; C2 D]\n", - "A[9,:] = 0\n", - "A[10,:] = 0\n", - "A[9, 1] = 1\n", - "A[10, 2] = 1\n", + "#A[9,:] = 0\n", + "#A[9, 1] = 1\n", + "#A[10,:] = 0\n", + "#A[10, 1] = 2\n", + "#A[10, 2] = -2\n", "full(A)" ] }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 120, "metadata": { "collapsed": false }, @@ -3008,11 +2912,11 @@ "data": { "text/plain": [ "2x8 Array{Float64,2}:\n", - " 0.0 0.0264182 0.0607535 0.0343352 7.72542 15.4508 0.0 0.0\n", - " 0.0 0.00858381 -0.0970891 -0.105673 -23.7764 -47.5528 0.0 0.0" + " 0.0 0.0277778 0.0277778 0.0 0.0 0.0 0.0 0.0\n", + " 0.0 0.0 -0.111111 -0.111111 -25.0 -50.0 0.0 0.0" ] }, - "execution_count": 81, + "execution_count": 120, "metadata": {}, "output_type": "execute_result" } @@ -3029,7 +2933,7 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 83, "metadata": { "collapsed": false }, @@ -3037,16 +2941,17 @@ { "data": { "text/plain": [ - "0.11453071182271284" + "Test Passed\n", + " Expression: isapprox(norm(sol[:,3]),0.11453071182271282)" ] }, - "execution_count": 82, + "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "norm(sol[:,3])" + "@test isapprox(norm(sol[:,3]), 0.11453071182271282)" ] }, { diff --git a/src/assembly.jl b/src/assembly.jl index 57838e4..970fffd 100644 --- a/src/assembly.jl +++ b/src/assembly.jl @@ -25,6 +25,13 @@ function append!(assembly::Assembly, sub_assembly::Assembly) append!(assembly.force_vector, sub_assembly.force_vector) end +function append!(assembly::BoundaryAssembly, sub_assembly::BoundaryAssembly) + append!(assembly.C1, sub_assembly.C1) + append!(assembly.C2, sub_assembly.C2) + append!(assembly.D, sub_assembly.D) + append!(assembly.g, sub_assembly.g) +end + function assemble!(assembly::Assembly, problem::AllProblems, time::Float64, empty_assembly::Bool=true) if empty_assembly empty!(assembly) @@ -34,17 +41,24 @@ function assemble!(assembly::Assembly, problem::AllProblems, time::Float64, empt end end +""" Decide assembly type from given problem type. """ +function new_assembly{P}(problem_type::Type{FieldProblem{P}}) + return FieldAssembly() +end + +""" Decide assembly type from given problem type. """ +function new_assembly{P}(problem_type::Type{BoundaryProblem{P}}) + return BoundaryAssembly() +end + function assemble(problem::AllProblems, elrange::UnitRange{Int64}, time::Real, optimize=false) elements = get_elements(problem)[elrange] - assembly = Assembly() + assembly = new_assembly(typeof(problem)) for (i, element) in enumerate(elements) assemble!(assembly, problem, element, time) end if optimize - dim1 = length(assembly.stiffness_matrix.I) optimize!(assembly) - dim2 = length(assembly.stiffness_matrix.I) - info("combine: dim1 = $dim1, dim2 = $dim2") end return assembly end @@ -53,11 +67,7 @@ function assemble(problem::AllProblems, time::Real, nchunks=10) ne = length(get_elements(problem)) kk = round(Int, collect(linspace(0, ne, nchunks+1))) slices = [kk[j]+1:kk[j+1] for j=1:nchunks] - -# sub_assemblies = map( (elrange) -> assemble(problem, elrange, time), slices) -# assembly = sum(sub_assemblies) - - assembly = Assembly() + assembly = new_assembly(typeof(problem)) for (j, elrange) in enumerate(slices) sub_assembly = assemble(problem, elrange, time) append!(assembly, sub_assembly) @@ -65,9 +75,6 @@ function assemble(problem::AllProblems, time::Real, nchunks=10) info("Assembly: ", round(j/nchunks*100,1), " % done. ") end end -# optimize!(assembly) -# dim = length(assembly.stiffness_matrix.I) -# info("dim of COO: $dim") return assembly end @@ -173,3 +180,4 @@ function Base.(:+)(ass1::Assembly, ass2::Assembly) force_vector = ass1.force_vector + ass2.force_vector return Assembly(mass_matrix, stiffness_matrix, force_vector) end + diff --git a/src/directsolver.jl b/src/directsolver.jl index 45fc641..fa5ee6a 100644 --- a/src/directsolver.jl +++ b/src/directsolver.jl @@ -38,11 +38,11 @@ function DirectSolver(name="DirectSolver") 1.0e-6, # convergence tolerance false, # dump matrices true, # reduce stiffness matrix - :CHOLMOD # method: CHOLMOD, UMFPACK, PETSc_GMRES + :UMFPACK # method: CHOLMOD, UMFPACK, PETSc_GMRES ) end -function push!(solver::DirectSolver, problem::Problem) +function push!(solver::DirectSolver, problem::FieldProblem) push!(solver.field_problems, problem) end @@ -138,9 +138,21 @@ function solve(K, f, C, g, ::Type{Val{:UMFPACK}}) return u[1:dim], u[dim+1:end] end +function solve(K, f, C1, C2, D, g, ::Type{Val{:UMFPACK}}) + t0 = time() + dim = size(K, 1) + A = [K C1'; C2 D] + b = [f; g] + nz1 = sort(unique(rowvals(A))) + nz2 = sort(unique(rowvals(A'))) + u = zeros(length(b)) + u[nz1] = lufact(A[nz1,nz2]) \ full(b[nz1]) + info("UMFPACK: solved in ", time()-t0, " seconds. norm = ", norm(u[1:dim])) + return u[1:dim], u[dim+1:end] +end """ Call solver to solve a set of problems. """ -function call(solver::DirectSolver, time::Number=0.0) +function call(solver::DirectSolver, time::Real=0.0) info("Starting solver $(solver.name)") info("# of field problems: $(length(solver.field_problems))") info("# of boundary problems: $(length(solver.boundary_problems))") @@ -201,7 +213,7 @@ function call(solver::DirectSolver, time::Number=0.0) tic(timing, "field assembly") info("Assembling field problems...") - field_assembly = Assembly() + field_assembly = FieldAssembly() for (i, problem) in enumerate(solver.field_problems) info("Assembling body $i: $(problem.name)") append!(field_assembly, assemble(problem, time)) @@ -216,36 +228,38 @@ function call(solver::DirectSolver, time::Number=0.0) tic(timing, "boundary assembly") info("Assembling boundary problems...") - boundary_assembly = Assembly() + boundary_assembly = BoundaryAssembly() for (i, problem) in enumerate(solver.boundary_problems) info("Assembling boundary $i: $(problem.name)") append!(boundary_assembly, assemble(problem, time)) end - C = sparse(boundary_assembly.stiffness_matrix, dim, dim) - g = sparse(boundary_assembly.force_vector, dim, 1) + + C1 = sparse(boundary_assembly.C1, dim, dim) + C2 = sparse(boundary_assembly.C2, dim, dim) + D = sparse(boundary_assembly.D, dim, dim) + g = sparse(boundary_assembly.g, dim, 1) boundary_assembly = nothing gc() toc(timing, "boundary assembly") - -# resize!(C, dim, dim) -# resize!(g, dim, 1) -# resize!(f, dim, 1) - tic(timing, "dump matrices to disk") if solver.dump_matrices filename = "matrices_$(solver.name)_host_$(myid())_iteration_$(iter).jld" info("dumping matrices to disk, file = $filename") - save(filename, "stiffness matrix", K, "force vector", f, - "constraint matrix lhs", C, "constraint matrix rhs", g) + save(filename, "stiffness matrix K", K, "force vector f", f, + "constraint matrix C1", C1, + "constraint matrix C2", C2, + "constraint matrix D", D, + "constraint vector g", g) end toc(timing, "dump matrices to disk") tic(timing, "solution of system") info("Solving system") gc() -# whos() - sol, la = solve(K, f, C, g, Val{solver.method}) +# sol, la = solve(K, f, C, g, Val{solver.method}) + sol, la = solve(K, f, C1, C2, D, g, Val{solver.method}) + gc() toc(timing, "solution of system") @@ -297,3 +311,4 @@ function call(solver::DirectSolver, time::Number=0.0) return (solver.max_iterations, false) end + diff --git a/src/dirichlet.jl b/src/dirichlet.jl index 853c09f..ce01a2c 100644 --- a/src/dirichlet.jl +++ b/src/dirichlet.jl @@ -10,7 +10,7 @@ function DirichletProblem(problem_name::ASCIIString, parent_field_name::ASCIIStr return BoundaryProblem{DirichletProblem}(problem_name, parent_field_name, parent_field_dim, dim, elements) end -function assemble!(assembly::Assembly, problem::BoundaryProblem{DirichletProblem}, element::Element, time::Number) +function assemble!(assembly::BoundaryAssembly, problem::BoundaryProblem{DirichletProblem}, element::Element, time::Real) # get dimension and name of PARENT field field_dim = problem.parent_field_dim @@ -34,18 +34,19 @@ function assemble!(assembly::Assembly, problem::BoundaryProblem{DirichletProblem for i=1:field_dim g = element(field_name, ip, time) ldofs = gdofs[i:field_dim:end] - add!(assembly.stiffness_matrix, ldofs, ldofs, A) - add!(assembly.force_vector, ldofs, w*g*N') + add!(assembly.C1, ldofs, ldofs, A) + add!(assembly.C2, ldofs, ldofs, A) + add!(assembly.g, ldofs, w*g*N') end end for i=1:field_dim - # add per dof if defined element["blaa 1"] = 1.0, element["blaa 2"] = 0.0 etc. if haskey(element, field_name*" $i") g = element(field_name*" $i", ip, time) ldofs = gdofs[i:field_dim:end] - add!(assembly.stiffness_matrix, ldofs, ldofs, A) - add!(assembly.force_vector, ldofs, w*g*N') + add!(assembly.C1, ldofs, ldofs, A) + add!(assembly.C2, ldofs, ldofs, A) + add!(assembly.g, ldofs, w*g*N') end end end diff --git a/src/elasticity.jl b/src/elasticity.jl index 646c346..cd510b4 100644 --- a/src/elasticity.jl +++ b/src/elasticity.jl @@ -24,6 +24,9 @@ end function PlaneStressElasticityProblem(dim::Int=2, elements=[]) return Problem{PlaneStressElasticityProblem}("plane stress elasticity problem", dim, elements) end +function PlaneStressElasticityProblem(problem_name::ASCIIString, dim::Int=2, elements=[]) + return Problem{PlaneStressElasticityProblem}(problem_name, dim, elements) +end """ Elasticity equations. diff --git a/src/equations.jl b/src/equations.jl index f284669..031573b 100644 --- a/src/equations.jl +++ b/src/equations.jl @@ -3,17 +3,39 @@ # Functions to handle element level things -- integration, assembly, ... -type Assembly - mass_matrix :: SparseMatrixIJV - stiffness_matrix :: SparseMatrixIJV - force_vector :: SparseMatrixIJV +type FieldAssembly + mass_matrix :: SparseMatrixCOO + stiffness_matrix :: SparseMatrixCOO + force_vector :: SparseMatrixCOO end -function Assembly() - return Assembly( - SparseMatrixIJV(), - SparseMatrixIJV(), - SparseMatrixIJV()) +function FieldAssembly() + return FieldAssembly( + SparseMatrixCOO(), + SparseMatrixCOO(), + SparseMatrixCOO()) +end + +typealias Assembly FieldAssembly + +""" +"Boundary" matrices C₁, C₂, D, g for general problem type +Au + C₁'λ = f +C₂u + Dλ = g +""" +type BoundaryAssembly + C1 :: SparseMatrixCOO + C2 :: SparseMatrixCOO + D :: SparseMatrixCOO + g :: SparseMatrixCOO +end + +function BoundaryAssembly() + return BoundaryAssembly( + SparseMatrixCOO(), + SparseMatrixCOO(), + SparseMatrixCOO(), + SparseMatrixCOO()) end function Base.empty!(assembly::Assembly) diff --git a/src/mortar.jl b/src/mortar.jl index 7d848f2..2cbc7b3 100644 --- a/src/mortar.jl +++ b/src/mortar.jl @@ -662,7 +662,7 @@ end typealias MortarElements2D Union{Seg2, Seg3} -function assemble!{E<:MortarElements2D}(assembly::Assembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element{E}, time::Real) +function assemble!{E<:MortarElements2D}(assembly::BoundaryAssembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element{E}, time::Real) # get dimension and name of PARENT field field_dim = problem.parent_field_dim @@ -675,13 +675,14 @@ function assemble!{E<:MortarElements2D}(assembly::Assembly, problem::BoundaryPro xi1b = project_from_master_to_slave(slave_element, master_element, [ 1.0]) xi1 = clamp([xi1a xi1b], -1.0, 1.0) l = 1/2*(xi1[2]-xi1[1]) - if abs(l) < 1.0e-6 - warn("No contribution") + if abs(l) < 1.0e-9 + #warn("No contribution") continue # no contribution end master_dofs = get_gdofs(master_element, field_dim) for ip in get_integration_points(slave_element, Val{5}) - w = ip.weight*det(slave_element, ip, time)*l + J = get_jacobian(slave_element, ip, time) + w = ip.weight*norm(J)*l # integration point on slave side segment xi_gauss = 1/2*(1-ip.xi)*xi1[1] + 1/2*(1+ip.xi)*xi1[2] @@ -692,15 +693,14 @@ function assemble!{E<:MortarElements2D}(assembly::Assembly, problem::BoundaryPro N1 = slave_element(xi_gauss, time) N2 = master_element(xi_projected, time) S = w*N1'*N1 - M = w*(N1'*N2)' -# M = w*N1'*N2 - # FIXME: why this needs now to be transpose? - # assembly / repeat + M = w*N1'*N2 for i=1:field_dim sd = slave_dofs[i:field_dim:end] md = master_dofs[i:field_dim:end] - add!(assembly.stiffness_matrix, sd, sd, S) - add!(assembly.stiffness_matrix, sd, md, -M) + add!(assembly.C1, sd, sd, S) + add!(assembly.C1, sd, md, -M) + add!(assembly.C2, sd, sd, S) + add!(assembly.C2, sd, md, -M) end end @@ -735,7 +735,7 @@ function find_master_elements(slave_element::Element, time::Real) return master_elements end -function assemble!{E<:MortarElements3D}(assembly::Assembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element{E}, time::Real) +function assemble!{E<:MortarElements3D}(assembly::BoundaryAssembly, problem::BoundaryProblem{MortarProblem}, slave_element::Element{E}, time::Real) field_dim = problem.parent_field_dim field_name = problem.parent_field_name slave_dofs = get_gdofs(slave_element, field_dim) @@ -893,13 +893,14 @@ function assemble!{E<:MortarElements3D}(assembly::Assembly, problem::BoundaryPro @debug info("weight S = $wS, weight M = $wM, weight C = $wC") Sm = ip.weight*N1'*N1*wC - # FIXME: master side transpose -- why? - Mm = ip.weight*(N1'*N2)'*wC + Mm = ip.weight*N1'*N2*wC for k=1:field_dim sd = slave_dofs[k:field_dim:end] md = master_dofs[k:field_dim:end] - add!(assembly.stiffness_matrix, sd, sd, Sm) - add!(assembly.stiffness_matrix, sd, md, -Mm) + add!(assembly.C1, sd, sd, Sm) + add!(assembly.C1, sd, md, -Mm) + add!(assembly.C2, sd, sd, Sm) + add!(assembly.C2, sd, md, -Mm) end end # info("breaking on first") diff --git a/src/problems.jl b/src/problems.jl index 7091b15..4d0e2bd 100644 --- a/src/problems.jl +++ b/src/problems.jl @@ -3,7 +3,7 @@ abstract AbstractProblem -type Problem{T<:AbstractProblem} +type FieldProblem{T<:AbstractProblem} name :: ASCIIString dim :: Int elements :: Vector{Element} @@ -17,9 +17,9 @@ type BoundaryProblem{T<:AbstractProblem} elements :: Vector{Element} end -typealias FieldProblem Problem +typealias Problem FieldProblem -typealias AllProblems Union{Problem, BoundaryProblem} +typealias AllProblems Union{FieldProblem, BoundaryProblem} function get_elements(problem::AllProblems) return problem.elements diff --git a/src/sparse.jl b/src/sparse.jl index 325fea9..9ce0e46 100644 --- a/src/sparse.jl +++ b/src/sparse.jl @@ -4,16 +4,23 @@ # Sparse utils to make assembly of local and global matrices easier. # Unoptimized but should do all necessary stuff for at start. -type SparseMatrixIJV +type SparseMatrixCOO I :: Vector{Int} J :: Vector{Int} V :: Vector{Float64} end -typealias SparseMatrixCOO SparseMatrixIJV +typealias SparseMatrixIJV SparseMatrixCOO +#= function SparseMatrixIJV() - SparseMatrixIJV([], [], []) + warn("use SparseMatrixCOO to construct sparse matrix.""") + SparseMatrixCOO([], [], []) +end +=# + +function SparseMatrixCOO() + SparseMatrixCOO([], [], []) end function Base.sparse(A::SparseMatrixIJV, args...) @@ -85,8 +92,8 @@ Example """ function add!(A::SparseMatrixIJV, dofs1::Vector{Int}, dofs2::Vector{Int}, data::Matrix{Float64}) n, m = size(data) - for i=1:n - for j=1:m + for j=1:m + for i=1:n push!(A.I, dofs1[i]) push!(A.J, dofs2[j]) end diff --git a/src/test.jl b/src/test.jl index b8e2441..5712592 100644 --- a/src/test.jl +++ b/src/test.jl @@ -1,7 +1,12 @@ # This file is a part of JuliaFEM. # License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md -using BaseTestNext +if VERSION >= v"0.5-" + using Base.Test +else + using BaseTestNext +end + abstract TestResult diff --git a/src/xdmf.jl b/src/xdmf.jl index 170aa5e..b6db5f2 100644 --- a/src/xdmf.jl +++ b/src/xdmf.jl @@ -37,6 +37,7 @@ using LightXML # > #define XDMF_3DCORECTMESH 0x1102 global eltypes = Dict{Symbol, Int}( + :Tri3 => 0x4, :Quad4 => 0x5, :Tet4 => 0x6, :Hex8 => 0x9, diff --git a/test/test_mortar.jl b/test/test_mortar.jl index 3add883..f18f738 100644 --- a/test/test_mortar.jl +++ b/test/test_mortar.jl @@ -1,7 +1,7 @@ # This file is a part of JuliaFEM. # License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md -module MortarTests +module MortarTests3D using JuliaFEM.Test @@ -9,9 +9,6 @@ using JuliaFEM.Core: Element, Seg2, Quad4, Tri3, Hex8, MortarProblem, Assembly, get_connectivity, update! using JuliaFEM.Core: PlaneStressElasticityProblem, DirichletProblem, DirectSolver -# 2d stuff -using JuliaFEM.Core: project_from_slave_to_master, project_from_master_to_slave - # 3d stuff using JuliaFEM.Core: create_auxiliary_plane, project_point_to_auxiliary_plane, get_edge_intersections, get_points_inside_triangle, @@ -22,352 +19,6 @@ using JuliaFEM.Core: create_auxiliary_plane, project_point_to_auxiliary_plane, using JuliaFEM.Core: LinearElasticityProblem -function get_test_2d_model() - # this is hand calculated and given as an example in my thesis - N = Vector[ - [0.0, 2.0], [1.0, 2.0], [2.0, 2.0], - [0.0, 0.0], [1.0, 0.0], [2.0, 0.0], - [0.0, 1.0], [5/4, 1.0], [2.0, 1.0], - [0.0, 1.0], [3/4, 1.0], [2.0, 1.0]] - rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)] - - master1 = Seg2([7, 8]) - master1["geometry"] = Vector[N[7], N[8]] - master2 = Seg2([8, 9]) - master2["geometry"] = Vector[N[8], N[9]] - -#= - master1 = Seg2([9, 8]) - master1["geometry"] = Vector[N[9], N[8]] - master2 = Seg2([8, 7]) - master2["geometry"] = Vector[N[8], N[7]] -=# - - slave1 = Seg2([10, 11]) - slave1["geometry"] = Vector[N[10], N[11]] - # should be n = [0 -1]' and t = [1 0]' - slave1["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] - slave1["master elements"] = Element[master1, master2] - - slave2 = Seg2([11, 12]) - slave2["geometry"] = Vector[N[11], N[12]] - # should be n = [0 -1]' and t = [1 0]' - slave2["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] - slave2["master elements"] = Element[master1, master2] - - return [slave1, slave2], [master1, master2] -end - - -function test_calc_flat_2d_projection_slave_to_master() - slaves, masters = get_test_2d_model() - slave1, slave2 = slaves - master1, master2 = masters - - xi2a = project_from_slave_to_master(slave1, master1, [-1.0]) - @test xi2a == [-1.0] - - xi2b = project_from_slave_to_master(slave1, master1, [1.0]) - @test xi2b == [ 0.2] - X2 = master1("geometry", xi2b, 0.0) - @test X2 == [3/4, 1.0] -end - - -function test_calc_flat_2d_projection_master_to_slave() - slaves, masters = get_test_2d_model() - slave1, slave2 = slaves - master1, master2 = masters - xi1a = project_from_master_to_slave(slave1, master1, [-1.0]) - @test xi1a == [-1.0] - xi1b = project_from_master_to_slave(slave1, master1, [1.0]) - X1 = slave1("geometry", xi1b, 0.0) - @test X1 == [5/4, 1.0] -end -#test_calc_flat_2d_projection_master_to_slave() - - -function test_calc_flat_2d_projection_rotated() - master1 = Seg2([3, 4]) - master1["geometry"] = Vector{Float64}[[0.0, 1.0], [0.0, 0.0]] - slave1 = Seg2([1, 2]) - slave1["geometry"] = Vector{Float64}[[0.0, 0.0], [0.0, 1.0]] - slave1["normal-tangential coordinates"] = Matrix{Float64}[[1.0 0.0; 0.0 1.0], [1.0 0.0; 0.0 1.0]] - xi = project_from_master_to_slave(slave1, master1, [-1.0]) - info("xi = $xi") - @test xi == [ 1.0] - xi = project_from_master_to_slave(slave1, master1, [1.0]) - info("xi = $xi") - @test xi == [-1.0] - - xi = project_from_slave_to_master(slave1, master1, [-1.0]) - info("xi = $xi") - @test xi == [ 1.0] - xi = project_from_slave_to_master(slave1, master1, [1.0]) - info("xi = $xi") - @test xi == [-1.0] - -end - - -function test_create_flat_2d_assembly() - slaves, masters = get_test_2d_model() - slave1, slave2 = slaves - master1, master2 = masters - - info("creating problem") - problem = MortarProblem("temperature", 1) - info("pushing slave elements to problem") - push!(problem, slave1) - push!(problem, slave2) - - B_expected = zeros(12, 12) - S1 = [10, 11] - M1 = [7, 8] - B_expected[S1,S1] += [1/4 1/8; 1/8 1/4] - B_expected[S1,M1] -= [3/10 3/40; 9/40 3/20] - - info("creating assembly") - assembly = Assembly() - assemble!(assembly, problem, slave1, 0.0) - B = round(full(assembly.stiffness_matrix, 12, 12), 6) - info("size of B = $(size(B))") - info("B matrix in first slave element = \n$(B[10:11,:])") - info("B matrix expected = \n$(B_expected[10:11,:])") - @test isapprox(B, B_expected) - - fill!(B_expected, 0.0) - empty!(assembly) - - S2 = [11, 12] - M2 = [7, 8] - B_expected[S2,S2] += [49/150 11/150; 11/150 2/75] - B_expected[S2,M2] -= [13/150 47/150; 1/75 13/150] - S3 = [11, 12] - M3 = [8, 9] - B_expected[S3,S3] += [9/100 27/200; 27/200 39/100] - B_expected[S3,M3] -= [3/20 3/40; 9/40 3/10] - assemble!(assembly, problem, slave2, 0.0) - B = full(assembly.stiffness_matrix) - info("size of B = $(size(B))") - info("B matrix in second slave element = \n$(B[11:12,:])") - info("B matrix expected = \n$(B_expected[11:12,:])") - - @test isapprox(B, B_expected) -end -#test_create_flat_2d_assembly() - - -function test_2d_mortar_multiple_bodies_multiple_dirichlet_bc() - N = Vector[ - [0.0, 0.0], [1.0, 0.0], - [0.0, 1.0], [1.0, 1.0], - [0.0, 1.0], [1.0, 1.0], - [0.0, 2.0], [1.0, 2.0]] - - e1 = Quad4([1, 2, 4, 3]) - e1["geometry"] = Vector[N[1], N[2], N[4], N[3]] - e2 = Quad4([5, 6, 8, 7]) - e2["geometry"] = Vector[N[5], N[6], N[8], N[7]] - for el in [e1, e2] - el["youngs modulus"] = 900.0 - el["poissons ratio"] = 0.25 - end - b1 = Seg2([7, 8]) - b1["geometry"] = Vector[N[7], N[8]] - b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]] - - body1 = PlaneStressElasticityProblem() - push!(body1, e1) - - body2 = PlaneStressElasticityProblem() - push!(body2, e2) - push!(body2, b1) - - # boundary elements for dirichlet dx=0 - dx1 = Seg2([1, 3]) - dx1["geometry"] = Vector[N[1], N[3]] - dx2 = Seg2([5, 7]) - dx2["geometry"] = Vector[N[5], N[7]] - for dx in [dx1, dx2] - dx["displacement 1"] = 0.0 - end - - boundary1 = DirichletProblem("displacement", 2) - push!(boundary1, dx1) - push!(boundary1, dx2) - - # boundary elements for dirichlet dy=0 - dy1 = Seg2([1, 2]) - dy1["geometry"] = Vector[N[1], N[2]] - dy1["displacement 2"] = 0.0 - - boundary2 = DirichletProblem("displacement", 2) - push!(boundary2, dy1) - - # mortar boundary between two bodies - rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)] - - master1 = Seg2([3, 4]) - master1["geometry"] = Vector[N[3], N[4]] - - slave1 = Seg2([5, 6]) - slave1["geometry"] = Vector[N[5], N[6]] - slave1["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] - slave1["master elements"] = Element[master1] - - boundary3 = MortarProblem("displacement", 2) - push!(boundary3, slave1) - - solver = DirectSolver() - push!(solver, body1) - push!(solver, body2) - push!(solver, boundary1) - push!(solver, boundary2) - push!(solver, boundary3) - - solver.name = "test_2d_mortar_multiple_bodies_multiple_dirichlet_bcs" - solver.dump_matrices = true - solver.method = :UMFPACK - # launch solver - solver(0.0) - - disp = e2("displacement", [1.0, 1.0], 0.0) - info("displacement at tip: $disp") - # code aster verification, two_elements.comm - @test isapprox(disp, [3.17431158889468E-02, -2.77183037855653E-01]) -end -#test_2d_mortar_multiple_bodies_multiple_dirichlet_bc() - - -function test_2d_mortar_three_bodies_shared_nodes() - N = Dict{Int, Vector{Float64}}( - 1 => [0.0, 0.0], - 2 => [2.0, 0.0], - 3 => [0.0, 1.0], - 4 => [2.0, 1.0], - 5 => [0.0, 1.0], - 6 => [1.3, 1.0], - 7 => [0.0, 2.0], - 8 => [1.3, 2.0], - 9 => [1.3, 1.0], - 10 => [2.0, 1.0], - 11 => [1.3, 2.0], - 12 => [2.0, 2.0]) - - e1 = Quad4([1, 2, 4, 3]) - e1["geometry"] = Vector[N[1], N[2], N[4], N[3]] - - e2 = Quad4([5, 6, 8, 7]) - e2["geometry"] = Vector[N[5], N[6], N[8], N[7]] - - e3 = Quad4([9, 10, 12, 11]) - e3["geometry"] = Vector[N[9], N[10], N[12], N[11]] - - for el in [e1, e2, e3] - el["youngs modulus"] = 900.0 - el["poissons ratio"] = 0.25 - end - - b1 = Seg2([7, 8]) - b1["geometry"] = Vector[N[7], N[8]] - b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]] - - b2 = Seg2([11, 12]) - b2["geometry"] = Vector[N[11], N[12]] - b2["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]] - - body1 = PlaneStressElasticityProblem() - push!(body1, e1) - - body2 = PlaneStressElasticityProblem() - push!(body2, e2) - push!(body2, b1) - - body3 = PlaneStressElasticityProblem() - push!(body3, e3) - push!(body3, b2) - - # boundary elements for dirichlet dx=0 - dx1 = Seg2([1, 3]) - dx1["geometry"] = Vector[N[1], N[3]] - dx2 = Seg2([5, 7]) - dx2["geometry"] = Vector[N[5], N[7]] - for dx in [dx1, dx2] - dx["displacement 1"] = 0.0 - end - - bc1 = DirichletProblem("displacement", 2) - push!(bc1, dx1) - push!(bc1, dx2) - - # boundary elements for dirichlet dy=0 - dy1 = Seg2([1, 2]) - dy1["geometry"] = Vector[N[1], N[2]] - dy1["displacement 2"] = 0.0 - - bc2 = DirichletProblem("displacement", 2) - push!(bc2, dy1) - - # mortar boundary between body 1 and body 2 - rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)] - - master1 = Seg2([3, 4]) - master1["geometry"] = Vector[N[3], N[4]] - - slave1 = Seg2([5, 6]) - slave1["geometry"] = Vector[N[5], N[6]] - slave1["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] - slave1["master elements"] = Element[master1] - bc3 = MortarProblem("displacement", 2) - push!(bc3, slave1) - - # mortar boundary between body 1 and body 3 - slave2 = Seg2([9, 10]) - slave2["geometry"] = Vector[N[9], N[10]] - slave2["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] - slave2["master elements"] = Element[master1] - bc4 = MortarProblem("displacement", 2) - push!(bc4, slave2) - - # mortar boundary between body 2 and body 3 - master2 = Seg2([9, 11]) - master2["geometry"] = Vector[N[9], N[11]] - - slave3 = Seg2([6, 8]) - slave3["geometry"] = Vector[N[6], N[8]] - #slave3["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] - slave3["normal-tangential coordinates"] = Matrix[rotation_matrix(0.0), rotation_matrix(0.0)] - slave3["master elements"] = Element[master2] - bc5 = MortarProblem("displacement", 2) - push!(bc5, slave3) - - solver = DirectSolver() - push!(solver, body1) - push!(solver, body2) - push!(solver, body3) - - push!(solver, bc1) - push!(solver, bc2) - - push!(solver, bc3) - push!(solver, bc4) - push!(solver, bc5) - - # launch solver - solver.method = :UMFPACK - solver.name = "test_2d_mortar_three_bodies_shared_nodes" - solver.dump_matrices = true - call(solver, 0.0) - - X = e3("geometry", [1.0, 1.0], 0.0) - u = e3("displacement", [1.0, 1.0], 0.0) - info("displacement at $X: $u") - # code aster verification, two_elements.comm - @test isapprox(u, [2*3.17431158889468E-02, -2.77183037855653E-01]) - -end -#test_2d_mortar_three_bodies_shared_nodes() function test_auxiliary_plane_transforms() diff --git a/test/test_mortar_2d.jl b/test/test_mortar_2d.jl new file mode 100644 index 0000000..88a585c --- /dev/null +++ b/test/test_mortar_2d.jl @@ -0,0 +1,355 @@ +# This file is a part of JuliaFEM. +# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md + +module MortarTests2D + +using JuliaFEM.Test + +using JuliaFEM.Core: Element, Seg2, Quad4, Tri3, Hex8, MortarProblem, Assembly, assemble, + get_connectivity, update!, assemble!, BoundaryAssembly +using JuliaFEM.Core: PlaneStressElasticityProblem, DirichletProblem, DirectSolver + +using JuliaFEM.Core: project_from_slave_to_master, project_from_master_to_slave + +function get_test_2d_model() + # this is hand calculated and given as an example in my thesis + N = Vector[ + [0.0, 2.0], [1.0, 2.0], [2.0, 2.0], + [0.0, 0.0], [1.0, 0.0], [2.0, 0.0], + [0.0, 1.0], [5/4, 1.0], [2.0, 1.0], + [0.0, 1.0], [3/4, 1.0], [2.0, 1.0]] + rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)] + + master1 = Seg2([7, 8]) + master1["geometry"] = Vector[N[7], N[8]] + master2 = Seg2([8, 9]) + master2["geometry"] = Vector[N[8], N[9]] + +#= + master1 = Seg2([9, 8]) + master1["geometry"] = Vector[N[9], N[8]] + master2 = Seg2([8, 7]) + master2["geometry"] = Vector[N[8], N[7]] +=# + + slave1 = Seg2([10, 11]) + slave1["geometry"] = Vector[N[10], N[11]] + # should be n = [0 -1]' and t = [1 0]' + slave1["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] + slave1["master elements"] = Element[master1, master2] + + slave2 = Seg2([11, 12]) + slave2["geometry"] = Vector[N[11], N[12]] + # should be n = [0 -1]' and t = [1 0]' + slave2["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] + slave2["master elements"] = Element[master1, master2] + + return [slave1, slave2], [master1, master2] +end + +@testset "2d mortar projection tests" begin + +@testset "calculate flat 2d projection from slave to master" begin + slaves, masters = get_test_2d_model() + slave1, slave2 = slaves + master1, master2 = masters + + xi2a = project_from_slave_to_master(slave1, master1, [-1.0]) + @test xi2a == [-1.0] + + xi2b = project_from_slave_to_master(slave1, master1, [1.0]) + @test xi2b == [ 0.2] + X2 = master1("geometry", xi2b, 0.0) + @test X2 == [3/4, 1.0] +end + +@testset "calculate flat 2d projection from master to slave" begin + slaves, masters = get_test_2d_model() + slave1, slave2 = slaves + master1, master2 = masters + xi1a = project_from_master_to_slave(slave1, master1, [-1.0]) + @test xi1a == [-1.0] + xi1b = project_from_master_to_slave(slave1, master1, [1.0]) + X1 = slave1("geometry", xi1b, 0.0) + @test X1 == [5/4, 1.0] +end + +@testset "calculate flat 2d projection rotated 90 degrees" begin + master1 = Seg2([3, 4]) + master1["geometry"] = Vector{Float64}[[0.0, 1.0], [0.0, 0.0]] + slave1 = Seg2([1, 2]) + slave1["geometry"] = Vector{Float64}[[0.0, 0.0], [0.0, 1.0]] + slave1["normal-tangential coordinates"] = Matrix{Float64}[[1.0 0.0; 0.0 1.0], [1.0 0.0; 0.0 1.0]] + xi = project_from_master_to_slave(slave1, master1, [-1.0]) + info("xi = $xi") + @test xi == [ 1.0] + xi = project_from_master_to_slave(slave1, master1, [1.0]) + info("xi = $xi") + @test xi == [-1.0] + + xi = project_from_slave_to_master(slave1, master1, [-1.0]) + info("xi = $xi") + @test xi == [ 1.0] + xi = project_from_slave_to_master(slave1, master1, [1.0]) + info("xi = $xi") + @test xi == [-1.0] + +end + +@testset "calculate flat 2d assembly" begin + slaves, masters = get_test_2d_model() + slave1, slave2 = slaves + master1, master2 = masters + + info("creating problem") + problem = MortarProblem("temperature", 1) + info("pushing slave elements to problem") + push!(problem, slave1) + push!(problem, slave2) + + B_expected = zeros(12, 12) + S1 = [10, 11] + M1 = [7, 8] + B_expected[S1,S1] += [1/4 1/8; 1/8 1/4] + B_expected[S1,M1] -= [3/10 3/40; 9/40 3/20] + + info("creating assembly") + assembly = BoundaryAssembly() + assemble!(assembly, problem, slave1, 0.0) + B = round(full(assembly.C1, 12, 12), 6) + info("size of B = $(size(B))") + info("B matrix in first slave element = \n$(B[10:11,:])") + info("B matrix expected = \n$(B_expected[10:11,:])") + @test isapprox(B, B_expected) + + fill!(B_expected, 0.0) + + S2 = [11, 12] + M2 = [7, 8] + B_expected[S2,S2] += [49/150 11/150; 11/150 2/75] + B_expected[S2,M2] -= [13/150 47/150; 1/75 13/150] + S3 = [11, 12] + M3 = [8, 9] + B_expected[S3,S3] += [9/100 27/200; 27/200 39/100] + B_expected[S3,M3] -= [3/20 3/40; 9/40 3/10] + assembly = BoundaryAssembly() + assemble!(assembly, problem, slave2, 0.0) + B = full(assembly.C1) + info("size of B = $(size(B))") + info("B matrix in second slave element = \n$(B[11:12,:])") + info("B matrix expected = \n$(B_expected[11:12,:])") + + @test isapprox(B, B_expected) +end + +@testset "test mortar problem with multiple dirichlet boundary conditions and multiple bodies" begin + N = Vector[ + [0.0, 0.0], [1.0, 0.0], + [0.0, 1.0], [1.0, 1.0], + [0.0, 1.0], [1.0, 1.0], + [0.0, 2.0], [1.0, 2.0]] + + e1 = Quad4([1, 2, 4, 3]) + e1["geometry"] = Vector[N[1], N[2], N[4], N[3]] + e2 = Quad4([5, 6, 8, 7]) + e2["geometry"] = Vector[N[5], N[6], N[8], N[7]] + for el in [e1, e2] + el["youngs modulus"] = 900.0 + el["poissons ratio"] = 0.25 + end + b1 = Seg2([7, 8]) + b1["geometry"] = Vector[N[7], N[8]] + b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]] + + body1 = PlaneStressElasticityProblem() + push!(body1, e1) + + body2 = PlaneStressElasticityProblem() + push!(body2, e2) + push!(body2, b1) + + # boundary elements for dirichlet dx=0 + dx1 = Seg2([1, 3]) + dx1["geometry"] = Vector[N[1], N[3]] + dx2 = Seg2([5, 7]) + dx2["geometry"] = Vector[N[5], N[7]] + for dx in [dx1, dx2] + dx["displacement 1"] = 0.0 + end + + boundary1 = DirichletProblem("displacement", 2) + push!(boundary1, dx1) + push!(boundary1, dx2) + + # boundary elements for dirichlet dy=0 + dy1 = Seg2([1, 2]) + dy1["geometry"] = Vector[N[1], N[2]] + dy1["displacement 2"] = 0.0 + + boundary2 = DirichletProblem("displacement", 2) + push!(boundary2, dy1) + + # mortar boundary between two bodies + rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)] + + master1 = Seg2([3, 4]) + master1["geometry"] = Vector[N[3], N[4]] + + slave1 = Seg2([5, 6]) + slave1["geometry"] = Vector[N[5], N[6]] + slave1["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] + slave1["master elements"] = Element[master1] + + boundary3 = MortarProblem("displacement", 2) + push!(boundary3, slave1) + + solver = DirectSolver() + push!(solver, body1) + push!(solver, body2) + push!(solver, boundary1) + push!(solver, boundary2) + push!(solver, boundary3) + + solver.name = "test_2d_mortar_multiple_bodies_multiple_dirichlet_bcs" + solver.dump_matrices = true + solver.method = :UMFPACK + # launch solver + solver(0.0) + + disp = e2("displacement", [1.0, 1.0], 0.0) + info("displacement at tip: $disp") + # code aster verification, two_elements.comm + @test isapprox(disp, [3.17431158889468E-02, -2.77183037855653E-01]) +end + +@testset "test 2d mortar problem with three bodies and shared nodes" begin + N = Dict{Int, Vector{Float64}}( + 1 => [0.0, 0.0], + 2 => [2.0, 0.0], + 3 => [0.0, 1.0], + 4 => [2.0, 1.0], + 5 => [0.0, 1.0], + 6 => [1.3, 1.0], + 7 => [0.0, 2.0], + 8 => [1.3, 2.0], + 9 => [1.3, 1.0], + 10 => [2.0, 1.0], + 11 => [1.3, 2.0], + 12 => [2.0, 2.0]) + + e1 = Quad4([1, 2, 4, 3]) + e1["geometry"] = Vector[N[1], N[2], N[4], N[3]] + + e2 = Quad4([5, 6, 8, 7]) + e2["geometry"] = Vector[N[5], N[6], N[8], N[7]] + + e3 = Quad4([9, 10, 12, 11]) + e3["geometry"] = Vector[N[9], N[10], N[12], N[11]] + + for el in [e1, e2, e3] + el["youngs modulus"] = 900.0 + el["poissons ratio"] = 0.25 + end + + b1 = Seg2([7, 8]) + b1["geometry"] = Vector[N[7], N[8]] + b1["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]] + + b2 = Seg2([11, 12]) + b2["geometry"] = Vector[N[11], N[12]] + b2["displacement traction force"] = Vector[[0.0, -100.0], [0.0, -100.0]] + + body1 = PlaneStressElasticityProblem() + push!(body1, e1) + + body2 = PlaneStressElasticityProblem() + push!(body2, e2) + push!(body2, b1) + + body3 = PlaneStressElasticityProblem() + push!(body3, e3) + push!(body3, b2) + + # boundary elements for dirichlet dx=0 + dx1 = Seg2([1, 3]) + dx1["geometry"] = Vector[N[1], N[3]] + dx2 = Seg2([5, 7]) + dx2["geometry"] = Vector[N[5], N[7]] + for dx in [dx1, dx2] + dx["displacement 1"] = 0.0 + end + + bc1 = DirichletProblem("displacement", 2) + push!(bc1, dx1) + push!(bc1, dx2) + + # boundary elements for dirichlet dy=0 + dy1 = Seg2([1, 2]) + dy1["geometry"] = Vector[N[1], N[2]] + dy1["displacement 2"] = 0.0 + + bc2 = DirichletProblem("displacement", 2) + push!(bc2, dy1) + + # mortar boundary between body 1 and body 2 + rotation_matrix(phi) = [cos(phi) -sin(phi); sin(phi) cos(phi)] + + master1 = Seg2([3, 4]) + master1["geometry"] = Vector[N[3], N[4]] + + slave1 = Seg2([5, 6]) + slave1["geometry"] = Vector[N[5], N[6]] + slave1["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] + slave1["master elements"] = Element[master1] + bc3 = MortarProblem("displacement", 2) + push!(bc3, slave1) + + # mortar boundary between body 1 and body 3 + slave2 = Seg2([9, 10]) + slave2["geometry"] = Vector[N[9], N[10]] + slave2["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] + slave2["master elements"] = Element[master1] + bc4 = MortarProblem("displacement", 2) + push!(bc4, slave2) + + # mortar boundary between body 2 and body 3 + master2 = Seg2([9, 11]) + master2["geometry"] = Vector[N[9], N[11]] + + slave3 = Seg2([6, 8]) + slave3["geometry"] = Vector[N[6], N[8]] + #slave3["normal-tangential coordinates"] = Matrix[rotation_matrix(-pi/2), rotation_matrix(-pi/2)] + slave3["normal-tangential coordinates"] = Matrix[rotation_matrix(0.0), rotation_matrix(0.0)] + slave3["master elements"] = Element[master2] + bc5 = MortarProblem("displacement", 2) + push!(bc5, slave3) + + solver = DirectSolver() + push!(solver, body1) + push!(solver, body2) + push!(solver, body3) + + push!(solver, bc1) + push!(solver, bc2) + + push!(solver, bc3) + push!(solver, bc4) + push!(solver, bc5) + + # launch solver + solver.method = :UMFPACK + solver.name = "test_2d_mortar_three_bodies_shared_nodes" + solver.dump_matrices = true + call(solver, 0.0) + + X = e3("geometry", [1.0, 1.0], 0.0) + u = e3("displacement", [1.0, 1.0], 0.0) + info("displacement at $X: $u") + # code aster verification, two_elements.comm + @test isapprox(u, [2*3.17431158889468E-02, -2.77183037855653E-01]) + +end + +end + +end