mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-17 17:22:10 +00:00
more general way to define saddle point problem.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -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)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+20
-12
@@ -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
|
||||
|
||||
|
||||
+31
-16
@@ -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
|
||||
|
||||
|
||||
+7
-6
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
+31
-9
@@ -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)
|
||||
|
||||
+16
-15
@@ -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")
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
+12
-5
@@ -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
|
||||
|
||||
+6
-1
@@ -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
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ using LightXML
|
||||
# > #define XDMF_3DCORECTMESH 0x1102
|
||||
|
||||
global eltypes = Dict{Symbol, Int}(
|
||||
:Tri3 => 0x4,
|
||||
:Quad4 => 0x5,
|
||||
:Tet4 => 0x6,
|
||||
:Hex8 => 0x9,
|
||||
|
||||
+1
-350
@@ -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()
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user