From 65eb014de909fccf4b375e5a2eaa27658976c5ec Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Tue, 23 Feb 2016 11:32:53 +0200 Subject: [PATCH] first attemps to make properly linearized version of mortar projection for finite sliding. not working at the moment, it has convergence issues. --- .../MESH_UPPER_BLOCK_SMALLER.med | Bin 0 -> 32586 bytes .../2d_curved_interface/PUNCH_AND_BLOCK.med | Bin 0 -> 86639 bytes .../2d_curved_interface/UPPER_SMALLER.med | Bin 0 -> 24974 bytes geometry/2d_curved_interface/model.hdf | Bin 440211 -> 780701 bytes geometry/2d_finite_sliding_test/TWOBLOCKS.med | Bin 0 -> 13293 bytes geometry/2d_finite_sliding_test/model.hdf | Bin 0 -> 277040 bytes src/elements.jl | 29 + src/fields.jl | 9 + src/lagrange.jl | 8 + src/mortar.jl | 720 +----------------- src/mortar_2d.jl | 5 +- src/mortar_2d_autodiff.jl | 674 ++++++++++++++++ src/mortar_3d.jl | 643 ++++++++++++++++ src/mortar_forwarddiff_pe.jl | 446 +++++++++++ src/problems.jl | 20 +- src/solvers.jl | 21 +- src/sparse.jl | 25 +- src/xdmf.jl | 4 +- 18 files changed, 1865 insertions(+), 739 deletions(-) create mode 100644 geometry/2d_curved_interface/MESH_UPPER_BLOCK_SMALLER.med create mode 100644 geometry/2d_curved_interface/PUNCH_AND_BLOCK.med create mode 100644 geometry/2d_curved_interface/UPPER_SMALLER.med create mode 100644 geometry/2d_finite_sliding_test/TWOBLOCKS.med create mode 100644 geometry/2d_finite_sliding_test/model.hdf create mode 100644 src/mortar_2d_autodiff.jl create mode 100644 src/mortar_3d.jl create mode 100644 src/mortar_forwarddiff_pe.jl diff --git a/geometry/2d_curved_interface/MESH_UPPER_BLOCK_SMALLER.med b/geometry/2d_curved_interface/MESH_UPPER_BLOCK_SMALLER.med new file mode 100644 index 0000000000000000000000000000000000000000..f40ad609b6ec8cca9868e57f63b1ff94609e8b87 GIT binary patch literal 32586 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 T(Q~gU&w{EBBqe%bO5lG1IB?RE literal 0 HcmV?d00001 diff --git a/geometry/2d_curved_interface/PUNCH_AND_BLOCK.med b/geometry/2d_curved_interface/PUNCH_AND_BLOCK.med new file mode 100644 index 0000000000000000000000000000000000000000..101ec9aac400d42321a69939b98a450998407787 GIT binary patch literal 86639 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󀱺ivf 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%0D%ZXFhUTD+qi?fxQF|AfQNX5$9RILc!uYAftPrN z*LZ`sc!&4+fRFfu&ycs7Ef57!5e?B112GW`u@MJx5fAZ^011%@iID_JkqpU^0x6LS zsgVY0kq+sR0U41AnUMuqkqz0A138fkxseBXkq`M%00mJ9g;4~SutHH3LvfTqNt8lq zltEdPgMc+`U<*6g!vT(PLU}mD1r^{5H@L$C6;TPE@PapdP#INF71dB3HBb|^P#eCe zgSx1P`e=ZLXoSXSf~IJO=J*}Yi1#Jle&~+@7>Gd_j3F3`VHl1P7>Q9BjWHODaTt#Y zn21T3j47CkX_$@~n2A}KjX9W$d6k{!oPa-0;uKEf49?;l&f@|u;u0?7 z3a;WBuHy!7;uZoBh#&+b1fjT%JGhH`xQ_>Th(~ygCwPiyc#ao%iC1`yH+YM8c#jYG zh)?(oo-i?3APS-)8locxVj>n|BMx{JCc^KTNX9bBkpd}^3aOC>X^{@;kpUTz37L@v zS&8KuMHBX_P@(l!JgZY+wsJ*uw#i za6)-F!vz)K3OBgJ0~JvTp74SMwXo99_ zhURF2mS~06XoI$BhxX`zj_8EW=z^~3hVJNr|H`xAi%IJeEX6V`#|o^(Dy+sDti?L4 z#|CV~CTzwQY{fQg#}4eoF6_o0?8QFp#{nF~AsogL9K|slhaXPBA184Nr*Q^naSrEk z0T*!zmvIGGaShjT12=IC0SH78f)RpH+{PW;#Xa1|13bhdJjN3|#WOs|3%tZDyv7^6 z#XG#m2YkdQe1?4L%mPsm710nKF%T265F2q27x54u36KzpkQhmj6v>brDUcGWkQ!-_ z7U_^48ITc~kQrH!71@v-Igk^%kQ;fB7x|DM1yB%$P#8sE2`dyuF%(A$ltd|%Mj4bv zIS5$82DY$+JsjW&CzOXXTu=e7aDzKMP!W~j2`_lV2bEC;RZ$JqQ3Ewm3$@{kI;e|! zsE-C{h(>6PCTNOgXpRXpau)h)(E?F6fGX%X8l|NXtyj!fedJT+G9K zEWko6!eT7JQY^!AtiVdF!fLF+TCBr*Y`{ir!e(s2R&2v|?7&X!!fx!rUhKnu9Kb;w z!eJc2Q5?f@_~8WnaT2F+8fS18=Wreua1obq8CP%>*Ki#-a1*x>fItKx7$FG7ZQQ|K z+{1l5z(YL3V?4oAJi~Lmz)QTsYrMf*yu*8Zz(;(-XBeW>{_$V@{h@-SyATSa2rOZR zq9}&qD1nkFh0-X4vM2`uYuLaRcCd#79N~oWaE1#iz!h$AhX*R656(G1Pe0xi)Bt<{9 literal 0 HcmV?d00001 diff --git a/geometry/2d_curved_interface/UPPER_SMALLER.med b/geometry/2d_curved_interface/UPPER_SMALLER.med new file mode 100644 index 0000000000000000000000000000000000000000..b0ec884f549728450f8d6da715534fef843c7990 GIT binary patch literal 24974 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 NYiS{^1m3|C_%E~`v-|)6 literal 0 HcmV?d00001 diff --git a/geometry/2d_curved_interface/model.hdf b/geometry/2d_curved_interface/model.hdf index 322b7ed112fc38ca6035050ffa7e7c8a17011297..fcbccc656cec5934e8aed41170ac160b2bd7c681 100644 GIT binary patch literal 780701 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

?PuJ&sZ^Em*Quk<56k8MzV*$!Z7IXo_p1Fa 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

    EK9$iEODc5%B8 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 S9NsA2dgFiKZx>EXvHbtoyHE-M diff --git a/geometry/2d_finite_sliding_test/TWOBLOCKS.med b/geometry/2d_finite_sliding_test/TWOBLOCKS.med new file mode 100644 index 0000000000000000000000000000000000000000..ee8536406114bfe164aa84dba0a0522274516d07 GIT binary patch literal 13293 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 literal 0 HcmV?d00001 diff --git a/src/elements.jl b/src/elements.jl index 608cfc8..4d59834 100644 --- a/src/elements.jl +++ b/src/elements.jl @@ -132,6 +132,35 @@ function call{E}(element::Element{E}, xi::VecOrIP, time::Float64=0.0) return get_basis(element, xi) end +""" Given a list of elementa and nodes, find a subset of elements +containing nodes. +""" +function find_elements(elements, nodes) + s = Set{Element}() + for element in elements + conn = get_connectivity(element) + for j in nodes + if j in conn + push!(s, element) + break + end + end + end + return collect(s) +end + +function get_gdofs(element::Element) + return get_gdofs(element, 1) +end + +function get_dbasis{E}(element::Element{E}, ip::IntegrationPoint) + return get_dbasis(E, ip.xi) +end + +function get_basis{E, T<:Real}(element::Element{E}, xi::T) + return get_basis(E, xi) +end + """ Return dual basis transformation matrix Ae. """ function get_dualbasis(element::Element, time::Real) if length(element.A) == 0 diff --git a/src/fields.jl b/src/fields.jl index 66e8b52..38857e0 100644 --- a/src/fields.jl +++ b/src/fields.jl @@ -216,6 +216,15 @@ function Base.(:*){T<:Real}(c::T, field::DVTI) return DVTI(c*field.data) end +""" Multiply DVTI field with another vector T. Vector length +must match to the field length and this can be used mainly +for interpolation purposes, i.e., u = ∑ Nᵢuᵢ +""" +function Base.(:*)(T::Vector, f::DVTI) + @assert length(T) == length(f) + return sum([T[i]*f[i] for i=1:length(f)]) +end + function Base.vec(field::DVTI) return [field.data...;] end diff --git a/src/lagrange.jl b/src/lagrange.jl index 98b278a..4a33f8c 100644 --- a/src/lagrange.jl +++ b/src/lagrange.jl @@ -140,3 +140,11 @@ end (xi) -> [ 1.0, xi[1], xi[2], xi[3], xi[1]^2, xi[2]^2, xi[3]^2, xi[1]*xi[2], xi[2]*xi[3], xi[3]*xi[1]]) + +# some helpers to make accessing 1d basis functions more easily +function get_basis{T<:Real, E<:Union{Seg2,Seg3}}(::Type{E}, xi::T) + get_basis(E, [xi]) +end +function get_dbasis{T<:Real, E<:Union{Seg2,Seg3}}(::Type{E}, xi::T) + get_dbasis(E, [xi]) +end diff --git a/src/mortar.jl b/src/mortar.jl index c2aee87..e1c8246 100644 --- a/src/mortar.jl +++ b/src/mortar.jl @@ -19,7 +19,7 @@ b) Remove inactive inequality constraints in assembly level. This is done in """ type Mortar <: BoundaryProblem - formulation :: Symbol # :total or :incremental + formulation :: Symbol # :total, :incremental, :autodiff dual_basis :: Bool inequality_constraints :: Bool # Launch PDASS to solve inequality constraints normal_condition :: Symbol # Tie or Contact @@ -31,10 +31,11 @@ type Mortar <: BoundaryProblem always_in_slip :: Vector{Int64} # nodes in this list always in slip contact :: Bool friction :: Bool + gap_sign :: Int # gap sign convention end function Mortar() - Mortar(:total, true, false, :Tie, :Stick, Inf, false, [], [], [], false, false) + Mortar(:total, true, false, :Tie, :Stick, Inf, false, [], [], [], false, false, -1) end function get_unknown_field_name(::Type{Mortar}) @@ -51,719 +52,8 @@ macro debug(msg) end include("mortar_2d.jl") - - -### Mortar projection calculation for 3d cases - -""" -Construct auxiliary plane for surface. - -Parameters ----------- -x::Array{Float64, 2} - Node coordinates -ximp::Array{Float64, 1} - Element mid-point in dimensionless mother element coordinates ξ -normals::Array{Float64, 2} - Normal directions in nodes - -Returns -------- -x0, Q - x0::Array{Float64, 1} - origo of auxiliary plane - Q::Array{Float64, 2} - orthogonal basis, first vector is normal direction - and two rest vectors create orthonormal right-handed basis. - -Examples --------- -Calculate auxiliary plane given nodal coordinates, midpoint of mother element, -node normals and suitable function space: - -julia> xquad = [ -... -2.5 2.5 2.0 -2.0 -... -2.0 -2.0 2.3 2.0 -... 1.0 0.7 0.0 1.0] -julia> m_midpoint = [0.0, 0.0] -julia> normals = [ -... 0.05989060 0.0590504 0.225612 0.2445800 -... -0.00748633 0.1670810 0.182034 -0.0305725 -... 0.99817700 0.9841730 0.957059 0.9691470] -julia> basis(xi) = [ -... (1-xi[1])(1-xi[2])/4 -... (1+xi[1])(1-xi[2])/4 -... (1+xi[1])(1+xi[2])/4 -... (1-xi[1])(1+xi[2])/4]' -julia> x0, Q = create_auxiliary_plane(xquad, mmidpoint, normals, basis) -julia> x0 -3-element Array{Float64,1}: - 0.0 - 0.075 - 0.675 -julia> Q -3x3 Array{Float64,2}: - 0.148586 0.988899 0.0 - 0.0784519 -0.0117877 0.996848 - 0.985783 -0.148118 -0.0793325 - -Notes ------ -- Midpoint in mother element typically (0, 0) for quadrangles and (1/3, 1/3) - for triangles. -- Uses Gram-Schmidt process to find orthogonal basis -- [1](http://www.math.umn.edu/~olver/aims_/qr.pdf) -- [2](http://www.ecs.umass.edu/ece/ece313/Online_help/gram.pdf) -- [3](http://www.terathon.com/code/tangent.html) - -""" -# function create_auxiliary_plane(x, ximp, normals, basis) -function create_auxiliary_plane{E}(element::Element{E}, time::Real) -# proj(u, v) = dot(v, u) / dot(u, u) * u -# xi = [1.0/3.0, 1.0/3.0] - - xi = get_reference_element_midpoint(E) - x0 = element("geometry", xi, time) - ntbasis = element("normal-tangential coordinates", xi, time) - return x0, ntbasis -#= - n = element("normal-tangential coordinates", xi, time)[:, 1] - n /= norm(n) - # gram-schmidt - u1 = n - j = indmax(abs(u1)) - v2 = zeros(3) - v2[mod(j,3)+1] = 1.0 - u2 = v2 - proj(u1, v2) - u3 = cross(u1, u2) - t1 = u2/norm(u2) - t2 = u3/norm(u3) - new_basis = [n t1 t2] - return x0, new_basis -=# -end - -""" -Project point q onto a plane given by a point p and normal n. - -Parameters ----------- -q::Array{Float64, 2} - point to project (row vector) -x0::Array{Float64, 2} - origo of plane -n::Array{Float64, 2} - normal vector of plane - -Returns -------- -y::Array{Float64, 2} - projected point - -Examples --------- -julia> p = [-0.5 -1.0 4.0]' -julia> x0 = [0.0 0.075 0.675]' -julia> n = [0.1485860 0.0784519 0.9857830]' -julia> project_node_to_auxiliary_plane(p, x0, n) -3-element Array{Float64,1}: - 0.963455 - -1.2447 - 0.925247 - -Notes ------ -[1](http://stackoverflow.com/questions/8942950/how-do-i-find-the-orthogonal-projection-of-a-point-onto-a-plane) - -""" -function project_point_to_auxiliary_plane(p::Vector, x0::Vector, Q::Matrix) - n = Q[:,1] - ph = p - dot(p-x0, n)*n - qproj = Q'*(ph-x0) - if !isapprox(qproj[1], 0.0; atol=1.0e-12) - info("project_point_to_auxiliary_plane(): point not projected correctly.") - info("p: $p") - info("x0: $x0") - info("Q: \n$Q") - info("qproj: $qproj") - error("Failed to project point to auxiliary plane.") - end - return qproj[2:3] -end - -""" -Find edge intersections of two planar arbitrary shape polygons. - -Parameters ----------- -S::Array{Float64,2} -M::Array{Float64,2} - -Matrices with size (2, n) where n is number of vertices of each polygon. - -Returns -------- -P::Array{Float64,2} - Intersection points of polygons -n::Array{Float64,2} - Neighbour info matrix with size (ns, mn). This keeps information which - edges of polygons are intersecting. See further explanation in example - below. - -Examples --------- -Find intersection points of two triangles: - -julia> S = [0 0; 3 0; 0 3]' -julia> M = [-1 1; 2 -1/2; 1 3/2]' -julia> P, n = get_edge_intersections(S, M) -julia> P -2x4 Array{Float64,2}: - 1.0 1.75 0.0 0.0 - 0.0 0.0 0.5 1.25 -julia> n -3x3 Array{Int64,2}: - 1 1 0 - 0 0 0 - 1 0 1) - -So intersection points are: (1.00, 0.00), (1.75, 0.00), (0.00, 0.50), (0.00, 1.25). -"Neighbour matrix" can be interpreted as following: - - 1 1 0 <--> First edge of S intersects edges 1 and 2 of M - 0 0 0 <--> Second edge of S doesn't intersect at all - 1 0 1 <--> Third edge of S intersects with edges 1 and 3 of M - -""" -function get_edge_intersections(S::Matrix, M::Matrix) - ns = size(S, 2) - nm = size(M, 2) - P = zeros(2, 0) - n = zeros(Int64, ns, nm) - k = 0 - for i=1:ns - for j=1:nm - b = M[:,j]-S[:,i] - A = [S[:,mod(i,ns)+1]-S[:,i] -M[:,mod(j,nm)+1]+M[:,j]] - if rank(A) == 2 - r = A\b - if (r[1]>=0) & (r[1]<=1) & (r[2]>=0) & (r[2]<=1) # intersection found - k += 1 - f = S[:,i]+r[1]*(S[:,mod(i,ns)+1] - S[:,i]) - f = f'' - P = hcat(P, f) - n[i, j] = 1 - end - end - end - end - return P, n -end - - -""" -Find any points laying inside or border of triangle. - -Parameters ----------- -Y::Array{Float64, 2} - Triangle coordinates in 2×3 matrix -X::Array{Float64, 2} - List of points to test in 2×n matrix - -Returns -------- -P::Array{Float64, 2} - List of points in triangle in 2×m matrix, where m is number of points inside triangle - -Examples --------- -julia> S = [0.0 0.0; 3.0 0.0; 0.0 3.0]' # triangle corner points -julia> pts = [-1.0 1.0; 2.0 -0.5; 1.0 1.5; 0.5 1.5]' # points to tests -julia> points_in_triangle(S, pts) -2x2 Array{Float64,2}: - 1.0 0.5 - 1.5 1.5 -""" -function get_points_inside_triangle(Y::Matrix, X::Matrix) - @assert size(Y, 2) == 3 # "Point in TRIANGLE..." - P = zeros(2, 0) - v0 = Y[:,2] - Y[:,1] - v1 = Y[:,3] - Y[:,1] # find interior points of X in Y - d00 = (v0'*v0)[1] - d01 = (v0'*v1)[1] - d11 = (v1'*v1)[1] # using baricentric coordinates - id = 1/(d00*d11 - d01*d01) - for i=1:size(X, 2) - v2 = X[:,i] - Y[:,1] - d02 = (v0'*v2)[1] - d12 = (v1'*v2)[1] - u = (d11*d02-d01*d12)*id - v = (d00*d12-d01*d02)*id - if (u>=0) & (v>=0) & (u+v<=1) # also include nodes on the boundary - P = hcat(P, X[:,i]'') - end - end - return P -end - -""" -Determine is point P inside or on boudary of polygon X. - -http://paulbourke.net/geometry/polygonmesh/#insidepoly -""" -function is_point_inside_convex_polygon(P, X) - x, y = P - for i=1:length(X) - x0, y0 = X[i] - x1, y1 = X[mod(i, length(X))+1] - if (y-y0)*(x1-x0) - (x-x0)*(y1-y0) < 0 - return false - end - end - return true -end - -function get_points_inside_convex_polygon(pts, X) - # TODO: Make more readable - X2 = [X[:,i] for i=1:size(X,2)] - c = filter(P->is_point_inside_convex_polygon(P, X2), [pts[:,i] for i=1:size(pts, 2)]) - return length(c) == 0 ? zeros(2, 0) : hcat(c...) -end - -""" Return unique objects with some given tolerance. This is used in next function - because traditional unique() command returns row vectors as non-unique if they - differs only a "little". -""" -function uniquetol(P, dim::Int; args...) - @assert dim == 2 - items = Vector{Float64}[P[:,i] for i=1:size(P,dim)] - new_items = Vector{Float64}[] - for item in items - has_found = false - for new_item in new_items - if isapprox(item, new_item; args...) - has_found = true - break - end - end - if !has_found - push!(new_items, item) - end - end - return reshape([new_items...;], length(new_items[]), length(new_items)) -end - - -""" -Make polygon clipping of shapes S and M. - -Parameters ----------- -S::Array{Float64, 2} -M::Array{Float64, 2} - Shapes to clip. Needs to be triangles at the moment. - -Returns -------- -Array{Float64, 2}, Array{Float64, 2} -- Polygon vertices in 2×n matrix, sorted in counter-clockwise order. -- 3×3 "neighbouring" matrix, see example. - -Examples --------- -julia> S = [0 0; 3 0; 0 3]' -julia> M = [-1 1; 2 -1/2; 2 2]' -julia> P, n = clip_polygon(S, M) -julia> P -2x6 Array{Float64,2}: - 0.0 1.0 2.0 2.0 1.25 0.0 - 0.5 0.0 0.0 1.0 1.75 1.33333, -julia> n -3x3 Array{Int64,2}: - 1 0 1 <- first edge of M ([-1 1; 2 -1/2]') intersects with edges 1 and 3 of S ([0 0; 3 0]' and [0 3; 0 0]') - 1 1 0 <- second edge of M ([2 -1/2; 2 2]') intersects with edges 1 and 2 of S - 0 1 1 <- third edge of M ([2 2; -1 1]') intersects with edgse 2 and 3 of S - -""" -function clip_polygon(S::Matrix, M::Matrix) - P1, neighbours = get_edge_intersections(M, S) - #P2 = get_points_inside_triangle(M, S) - #P3 = get_points_inside_triangle(S, M) - P2 = get_points_inside_convex_polygon(M, S) - P3 = get_points_inside_convex_polygon(S, M) -# info("polygon clipping: P1 = $P1") -# info("polygon clipping: P2 = $P2") -# info("polygon clipping: P3 = $P3") -# info("hcat P = $P") - P = hcat(P1, P2, P3) - if length(P) == 0 - return nothing, nothing - end - P = uniquetol(P, 2) - meanval = mean(P, 2) - tmp = P .- meanval - angles = atan2(tmp[2,:], tmp[1,:]) - angles = reshape(angles, length(angles)) - order = sortperm(angles) - return P[:, order], neighbours -end - - -""" -Calculate polygon geometric center point - -Parameters ----------- -P::Array{Float64, 2} - Polygon vertices in 2×n matrix - -Returns -------- -Array{Float63, 2} - Center point - -Examples --------- -julia> P -2x6 Array{Float64,2}: - 0.0 1.0 2.0 2.0 1.25 0.0 - 0.5 0.0 0.0 1.0 1.75 1.33333, -julia> C = get_polygon_cp(P) -2x1 Array{Float64,2}: - 1.039740 - 0.804701 - -""" -function calculate_polygon_centerpoint(P::Matrix) - n = size(P, 2) - A = 0.0 - for i=1:n - A += 1/2*(P[1,i]*P[2,mod(i,n)+1] - P[1,mod(i,n)+1]*P[2,i]) - end - Cx = 0.0 - Cy = 0.0 - for i=1:n - inext = mod(i, n)+1 - Cx += 1/(6*A)*(P[1,i] + P[1,inext])*(P[1,i]*P[2,inext] - P[1,inext]*P[2,i]) - Cy += 1/(6*A)*(P[2,i] + P[2,inext])*(P[1,i]*P[2,inext] - P[1,inext]*P[2,i]) - end - return Float64[Cx, Cy] -end - -""" -Project point from auxiliary plane to parametric surface given by (ξ₁, ξ₂) - -Parameters ----------- -p::Array{Float64,1} - point in auxiliary plane, in (n,t1,t2) coordinate system -x0::Array{Float64,1} - origo of auxiliary plane cs -Q::Array{Float64,2} - basis of auxiliary plane cs -x::Array{Float64,2} - surface node coords -basis::Array{Float64,2} - surface basis functions -dbasis::Array{Float64,2} - partial derivatives of surface basis functions - -Returns -------- -Array{Float64,2} - solution vector (d, ξ₁, ξ₂) where d is distance to surface - -Examples --------- -Define surface with node points, basis + dbasis - -julia> xquad = [ -... -2.5 -2.0 1.0 -... 2.5 -2.0 0.7 -... 2.0 2.3 0.0 -... -2.0 2.0 1.0]' -julia> basis(xi) = [ -... (1-xi[1])(1-xi[2])/4 -... (1+xi[1])(1-xi[2])/4 -... (1+xi[1])(1+xi[2])/4 -... (1-xi[1])(1+xi[2])/4] -julia> dbasis(xi) = [ -... -(1-xi[2])/4 -(1-xi[1])/4 -... (1-xi[2])/4 -(1+xi[1])/4 -... (1+xi[2])/4 (1+xi[1])/4 -... -(1+xi[2])/4 (1-xi[1])/4] - -We aim to find point p, which we first project to auxiliary plane defined as following -julia> p = [-2.5 -2.0 1.0]' -julia> x0 = [0.0 0.075 0.675]' -julia> Q = [ -... 0.1485860 0.9888990 0.0000000 -... 0.0784519 -0.0117877 0.9968480 -... 0.9857830 -0.1481180 -0.0793325] - -Our projected point is therefore -julia> n = Q[:,1] # first component is normal direction -julia> ph = project_node_to_auxiliary_plane(p, x0, n) -julia> ph = Q'(ph-x0) -julia> ph -3x1 Array{Float64,2}: - 1.33264e-7 - -2.49593 - -2.09424 - -Our point ph is now in auxiliary plane in n,t1,t2 coordinate system. Next we -project it back to surface defined by xquad*basis - -julia> theta = project_point_from_plane_to_surface(ph, x0, Q, xquad, basis, dbasis) -julia> theta -3x1 Array{Float64,2}: - -0.213874 - -0.999999 - -1.0 - -We see that our ξ₁ = ξ₂ = -1 so we found first point of xquad -[-2.5 -2.0 1.0]' correctly. - -julia> xquad*basis(theta[2:3]) -3-element Array{Float64,1}: - -2.5 - -2.0 - 1.0 - -""" -function project_point_from_plane_to_surface{E}(p::Vector, x0::Vector, Q::Matrix, element::Element{E}, time::Real; max_iterations::Int=10, iter_tol::Float64=1.0e-9) - basis(xi) = get_basis(E, xi) - dbasis(xi) = get_dbasis(E, xi) - x = element("geometry", time) - ph = Q*[0; p] + x0 - theta = Float64[0.0, 0.0, 0.0] - n = Q[:,1] - for i=1:max_iterations - b = ph + theta[1]*n - basis(theta[2:3])*x - J = [n -dbasis(theta[2:3])*x] - dtheta = J \ -b - theta += dtheta - if norm(dtheta) < iter_tol - return theta - end - end - begin - info("projecting point from auxiliary plane back to surface didn't go very well.") - info("element type: $E") - info("element connectivity: $(get_connectivity(element))") - info("auxiliary plane: x0 = $x0, Q = $Q") - info("point coordinates on plane: $p") - info("element geometry: $x") - info("ph: $ph") - info("normal direction: $n") - info("parameter vector before giving up: $theta") - end - error("project_point_to_surface: did not converge in $max_iterations iterations!") -end - -typealias MortarElements3D Union{Tri3, Quad4} - -function assemble!{E<:MortarElements3D}(assembly::Assembly, problem::Problem{Mortar}, - slave_element::Element{E}, time::Real) - haskey(slave_element, "master elements") || return - field_dim = get_unknown_field_dimension(problem) - field_name = get_parent_field_name(problem) - slave_dofs = get_gdofs(slave_element, field_dim) - - props = problem.properties - if props.formulation == :Standard && props.normal_condition == :Contact - error("for contact choose Dual formulation.""") - end - - # create auxiliary plane and project slave nodes to it - # x0 = origo, Q = local basis - x0, Q = create_auxiliary_plane(slave_element, time) - - # 1. project slave nodes to auxiliary plane - Sl = Vector{Float64}[] - for p in slave_element("geometry", time) - push!(Sl, project_point_to_auxiliary_plane(p, x0, Q)) - end - S = hcat(Sl...) - - for master_element in slave_element["master elements"] - - # if distance between elements is "far enough" cannot expect contact - if (props.normal_condition == :Contact) || props.inequality_constraints - slave_midpoint = slave_element("geometry", [0.0, 0.0], time) - master_midpoint = master_element("geometry", [0.0, 0.0], time) - if norm(slave_midpoint - master_midpoint) > props.minimum_distance - continue - end - end - - master_dofs = get_gdofs(master_element, field_dim) - - # 2. project master nodes to auxiliary plane - M = Vector{Float64}[] - for p in master_element("geometry", time) - push!(M, project_point_to_auxiliary_plane(p, x0, Q)) - end - M = hcat(M...) - - # 3. create polygon clipping on auxiliary plane - P = nothing - neighbours = nothing - try - P, neighbours = clip_polygon(S, M) - catch - info("polygon clipping failed") - info("S = ") - dump(S) - info("M = ") - dump(M) - info("original Sl = ") - info(Sl) - error("cannot continue") - end - isa(P, Void) && continue # no clipping - - # shared edge but no shared volume. skipping - size(P, 2) < 3 && continue - - C = calculate_polygon_centerpoint(P) - npts = size(P, 2) # number of vertices in polygon - - # loop vertices and create temporary integrate cells - # TODO: basically when npts == 3 or npts == 4 we could integrate without splitting to cells. - nnodes = size(slave_element, 2) - C1S3 = zeros(3*nnodes, 3*nnodes) - C1M3 = zeros(3*nnodes, 3*nnodes) - - for pnt=1:npts # integration of mortar matrices begin - cell = Field(Vector{Float64}[C, P[:,pnt], P[:,mod(pnt,npts)+1]]) - - # calculate slave side projection matrix D - # construct dual basis - Ae = zeros(nnodes, nnodes) - De = zeros(nnodes, nnodes) - Me = zeros(nnodes, nnodes) - if problem.properties.formulation == :Dual # Construct dual basis - for ip in get_integration_points(Tri3, Val{5}) - N = get_basis(Tri3, ip.xi) - xi = vec(N*cell) - theta = project_point_from_plane_to_surface(xi, x0, Q, slave_element, time) - xi_slave = theta[2:3] - N1 = slave_element(xi_slave, time) - # jacobian determinant on integration cell - dNC = get_dbasis(Tri3, ip.xi) - JC = sum([kron(dNC[:,j], cell[j]') for j=1:length(cell)]) - wC = ip.weight*det(JC) - De += wC*diagm(vec(N1)) - Me += wC*N1'*N1 - end - Ae = De*inv(Me) - end - for i=1:field_dim - C1S3[i:field_dim:end,i:field_dim:end] += De - end - - # Calculate master side projection matrix M - for ip in get_integration_points(Tri3, Val{5}) - # gauss point in auxiliary plane - #N = get_basis(E, ip.xi) - N = get_basis(Tri3, ip.xi) - xi = vec(N*cell) # xi defined in auxilary plane - - # find projection of gauss point to master and slave elements - theta1 = project_point_from_plane_to_surface(xi, x0, Q, slave_element, time) - theta2 = project_point_from_plane_to_surface(xi, x0, Q, master_element, time) - xi_slave = theta1[2:3] - xi_master = theta2[2:3] - - # evaluate shape functions values in gauss point and add contribution to matrices - N1 = slave_element(xi_slave, time) - N2 = master_element(xi_master, time) - - # jacobian determinant on integration cell - dNC = get_dbasis(Tri3, ip.xi) - JC = sum([kron(dNC[:,j], cell[j]') for j=1:length(cell)]) - wC = ip.weight*det(JC) - - # extend matrices according to the problem dimension (3) - @assert length(slave_dofs) == length(master_dofs) - Me = wC*Ae*N1'*N2 - for k=1:field_dim - C1M3[k:field_dim:end,k:field_dim:end] += Me - end - end - end # integration of mortar matrices done. - - # constraints in normal-tangential direction and initial weighted gap - X1 = vec(slave_element("geometry", time)) - X2 = vec(master_element("geometry", time)) - Q_ = slave_element("normal-tangential coordinates", time) - Z = zeros(3, 3) - if nnodes == 3 - Q3 = [Q Z Z; Z Q Z; Z Z Q] - elseif nnodes == 4 - Q3 = [Q Z Z Z; Z Q Z Z; Z Z Q Z; Z Z Z Q] - end - D3 = zeros(3*nnodes, 3*nnodes) - C2S3 = Q3'*C1S3 - C2M3 = Q3'*C1M3 - G = -(C2S3*X1 - C2M3*X2) - - # complementarity condition - if haskey(slave_element, "displacement") - u1 = vec(slave_element("displacement", time)) - else - u1 = zeros(3*nnodes) - end - if haskey(master_element, "displacement") - u2 = vec(master_element("displacement", time)) - else - u2 = zeros(3*nnodes) - end - x1 = X1 + u1 - x2 = X2 + u2 - if haskey(slave_element, "reaction force") - la = vec(slave_element("reaction force", time)) - else - la = zeros(3*nnodes) - end - g = -(C2S3*x1 - C2M3*x2) - c = Q3'*la - g - inactive_nodes = find(c[1:field_dim:end] .<= 0) - active_nodes = find(c[1:field_dim:end] .> 0) - - # normal constraint: remove inactive nodes if normal condition is set to contact - if problem.properties.normal_condition == :Contact - for j in inactive_nodes - dofs = [3*(j-1)+1, 3*(j-1)+2, 3*(j-1)+3] - G[dofs] = 0 - C1S3[dofs,:] = 0 - C1M3[dofs,:] = 0 - C2S3[dofs,:] = 0 - C2M3[dofs,:] = 0 - end - end - - # tangential constraint: stick or slip - if problem.properties.tangential_condition == :Slip - D3 = copy(C2S3) - D3[1:field_dim:end, :] = 0 - C2S3[2:field_dim:end, :] = 0 - C2M3[2:field_dim:end, :] = 0 - C2S3[3:field_dim:end, :] = 0 - C2M3[3:field_dim:end, :] = 0 - end - - # add contributions - add!(assembly.C1, slave_dofs, slave_dofs, C1S3) - add!(assembly.C1, slave_dofs, master_dofs, -C1M3) - add!(assembly.C2, slave_dofs, slave_dofs, C2S3) - add!(assembly.C2, slave_dofs, master_dofs, -C2M3) - add!(assembly.D, slave_dofs, slave_dofs, D3) - add!(assembly.c, slave_dofs, c) - add!(assembly.g, slave_dofs, G) - end -end - +include("mortar_2d_autodiff.jl") +include("mortar_3d.jl") """ Remove inactive inequality constraints by using primal-dual active set strategy. """ function boundary_assembly_posthook!(solver::Solver, problem::Problem{Mortar}, C1, C2, D, g) diff --git a/src/mortar_2d.jl b/src/mortar_2d.jl index 64845eb..74da3dc 100644 --- a/src/mortar_2d.jl +++ b/src/mortar_2d.jl @@ -217,7 +217,6 @@ function project_from_master_to_slave{S,M}(slave::Element{S}, master::Element{M} error("find projection from master to slave: did not converge") end - # Mortar assembly 2d # quadratic not tested yet @@ -546,8 +545,8 @@ function assemble!{E<:MortarElements2D}(assembly::Assembly, problem::Problem{Mor # Calculate normal-tangential constraints and weighted gap C2S2 = Q2'*C1S2 C2M2 = Q2'*C1M2 - G += -(C2S2*X1 - C2M2*X2) - g += -(C2S2*x1 - C2M2*x2) + G += props.gap_sign*(C2S2*X1 - C2M2*X2) + g += props.gap_sign*(C2S2*x1 - C2M2*x2) # Add contributions add!(local_assembly.C1, slave_dofs, slave_dofs, C1S2) diff --git a/src/mortar_2d_autodiff.jl b/src/mortar_2d_autodiff.jl new file mode 100644 index 0000000..b4d2cbb --- /dev/null +++ b/src/mortar_2d_autodiff.jl @@ -0,0 +1,674 @@ +# This file is a part of JuliaFEM. +# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md + +""" Find segment from slave element corresponding to master element nodes. +x1_, n1_ +slave element geometry and normal direction + +x2_ master element nodes to project onto slave +""" +function project_from_master_to_slave{E<:MortarElements2D}( + slave_element::Element{E}, x1_::DVTI, n1_::DVTI, x2::Vector; + tol=1.0e-10, max_iterations=20) + + function x1(xi1) + N = get_basis(E, xi1) + return vec(N)*x1_ + end + + function dx1(xi1) + dN = get_dbasis(E, xi1) + return vec(dN)*x1_ + end + + function n1(xi1) + N = get_basis(E, xi1) + return vec(N)*n1_ + end + + function dn1(xi1) + dN = get_dbasis(E, xi1) + return vec(dN)*n1_ + end + + cross2(a, b) = cross([a; 0], [b; 0])[3] + R(xi1) = cross2(x1(xi1)-x2, n1(xi1)) + dR(xi1) = cross2(dx1(xi1), n1(xi1)) + cross2(x1(xi1)-x2, dn1(xi1)) + xi1 = 0.0 + dxi1 = 0.0 + for i=1:max_iterations + dxi1 = -R(xi1)/dR(xi1) + xi1 += dxi1 + if norm(dxi1) < tol + return xi1 + end + end + + info("x1 = $(ForwardDiff.get_value(x1_.data))") + info("n1 = $(ForwardDiff.get_value(n1_.data))") + info("x2 = $(ForwardDiff.get_value(x2))") + info("xi1 = $(ForwardDiff.get_value(xi1)), dxi1 = $(ForwardDiff.get_value(dxi1))") + info("-R(xi1) = $(ForwardDiff.get_value(-R(xi1)))") + info("dR(xi1) = $(ForwardDiff.get_value(dR(xi1)))") + error("find projection from master to slave: did not converge") + +end + +function project_from_slave_to_master{E<:MortarElements2D}( + master_element::Element{E}, x1::Vector, n1::Vector, x2_::DVTI; + tol=1.0e-10, max_iterations=20) + + function x2(xi2) + N = get_basis(E, xi2) + return vec(N)*x2_ + end + + function dx2(xi2) + dN = get_dbasis(E, xi2) + return vec(dN)*x2_ + end + + cross2(a, b) = cross([a; 0], [b; 0])[3] + R(xi2) = cross2(x2(xi2)-x1, n1) + dR(xi2) = cross2(dx2(xi2), n1) + xi2 = 0.0 + dxi2 = 0.0 + for i=1:max_iterations + dxi2 = -R(xi2) / dR(xi2) + xi2 += dxi2 + if norm(dxi2) < tol + return xi2 + end + end + + error("find projection from slave to master: did not converge, last val: $xi2 and $dxi2") + +end + + +function assemble!{E<:MortarElements2D}(assembly::Assembly, problem::Problem{Mortar}, slave_element::Element{E}, time::Real, + ::Type{Val{:forwarddiff_old}}) + haskey(slave_element, "master elements") || return + props = problem.properties + field_dim = get_unknown_field_dimension(problem) + field_name = get_parent_field_name(problem) + slave_dofs = get_gdofs(slave_element, field_dim) + nnodes = size(slave_element, 2) + X1 = slave_element("geometry", time) + #u1 = slave_element("displacement", time) + #x1 = X1 + u1 + slave_element_nodes = get_connectivity(slave_element) + adjacent_elements = find_elements(get_elements(problem), slave_element_nodes) + adjacent_nodes = get_nodes(adjacent_elements) # including also nodes from adjacent elements + Q = [0.0 -1.0; 1.0 0.0] + + X = spzeros(10000, 1) + for element in get_elements(problem) + conn = get_connectivity(element) + geom = element("geometry", time) + for (c, g) in zip(conn, geom) + dofs = [field_dim*(c-1)+1, field_dim*(c-1)+2] + X[dofs] = g + end + end + + # here x does not mean deformed configuration + x = [problem.assembly.u; problem.assembly.la] + if length(x) == 0 + info("mortar_2d_autodiff: length(x) == 0") + # resize solution vectors according to initial configuration of this problem + X = vec(full(sparse(findnz(X)...))) + x = zeros(length(X)*2) + else + # resize initial configuration to match real dimension + I, J, V = findnz(X) + X = vec(full(sparse(I, J, V, length(problem.assembly.u), 1))) + end + ndofs = round(Int, length(x)/2) + # at the end we should have +# info("mortar_2d_autodiff: size of x = $(size(x))") +# info("mortar_2d_autodiff: size of X = $(size(X))") +# info("mortar_2d_autodiff: ndofs = $ndofs") + + """ Calculate normal vector for slave element nodes in current configuration. """ + function calculate_normals(u::Matrix) + normals = zeros(u) + # 1. update nodal normals + for element in adjacent_elements + conn = get_connectivity(element) + gdofs = get_gdofs(element, field_dim) + X_el = element("geometry", time) + u_el = Field(Vector[u[:, i] for i in conn]) + x_el = X_el + u_el + for ip in get_integration_points(element, Val{3}) + dN = get_dbasis(element, ip) + N = element(ip, time) + t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)]) + normals[:, conn] += ip.weight*Q*t'*N + end + end + slave_normals = Field(Vector[normals[:,i]/norm(normals[:,i]) for i in slave_element_nodes]) + return slave_normals + end + + function calculate_mortar_projection(u::Matrix, n1::DVTI) + B = SparseMatrixCOO{Real}([], [], []) + + u1 = Field([u[:,i] for i in slave_element_nodes]) + x1 = X1 + u1 + + for master_element in slave_element["master elements"] + X2 = master_element("geometry", time) + master_element_nodes = get_connectivity(master_element) + u2 = Field([u[:,i] for i in master_element_nodes]) + x2 = X2 + u2 + #info("master element coordinate 1 = $(ForwardDiff.get_value(x2[1]))") + #info("master element coordinate 2 = $(ForwardDiff.get_value(x2[2]))") + + # calculate segmentation: we care only about endpoints + # note: these are quadratic/cubic functions, analytical solution possible + xi1a = project_from_master_to_slave(slave_element, x1, n1, x2[1]) + xi1b = project_from_master_to_slave(slave_element, x1, n1, x2[end]) + xi1 = clamp([xi1a; xi1b], -1.0, 1.0) + l = 1/2*abs(xi1[2]-xi1[1]) + isapprox(l, 0.0) && continue # no contribution + + # integrate slave side + D = zeros(nnodes, nnodes) + Me = zeros(nnodes, nnodes) + for ip in get_integration_points(slave_element, Val{5}) + dN = get_dbasis(slave_element, ip) + # jacobian of slave element in deformed state + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N = get_basis(slave_element, xi_s) + D += w*diagm(vec(N)) + Me += w*N'*N + end + Ae = D*inv(Me) + + # integrate master side + M = zeros(nnodes, nnodes) + for ip in get_integration_points(slave_element, Val{5}) + dN = get_dbasis(slave_element, ip) + # jacobian of slave element in deformed state + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_g = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = get_basis(slave_element, xi_g) + x_g = vec(N1)*x1 + n_g = vec(N1)*n1 + #info("slave gauss point coordinates $(ForwardDiff.get_value(x_g))") + #info("slave gauss point normal direction $(ForwardDiff.get_value(n_g))") + xi_m = project_from_slave_to_master(master_element, x_g, n_g, x2) + N2 = get_basis(master_element, xi_m) + M += w*kron(Ae*N1', N2) + end + + slave_dofs = get_gdofs(slave_element, field_dim) + master_dofs = get_gdofs(master_element, field_dim) + for i=1:field_dim + add!(B, slave_dofs[i:field_dim:end], slave_dofs[i:field_dim:end], D) + add!(B, slave_dofs[i:field_dim:end], master_dofs[i:field_dim:end], -M) + end + + end + + return B + end + + function calculate_contact_rhs(x::Vector) + ndofs = round(Int, length(x)/2) + u = x[1:ndofs] + la = x[ndofs+1:end] +# info("calculate_contact_rhs: size of u = $(size(u))") +# info("calculate_contact_rhs: size of X = $(size(X))") +# info("calculate_contact_rhs: size of la = $(size(la))") +# info("calculate_contact_rhs: ndofs = $ndofs") + u2 = reshape(u, field_dim, round(Int, length(u)/field_dim)) + + normals = calculate_normals(u2) + B = calculate_mortar_projection(u2, normals) + B = sparse(B, ndofs, ndofs) + fc = B' * la # contact force residual for r = fint + fc - fext = 0 + + N = SparseMatrixCOO{Real}([], [], []) + T = SparseMatrixCOO{Real}([], [], []) + for (i, j) in enumerate(slave_element_nodes) + dofs = [2*(j-1)+1, 2*(j-1)+2] + add!(N, dofs, [dofs[1]], reshape(normals[i], 2, 1)) + add!(T, dofs, [dofs[2]], reshape(Q'*normals[i], 2, 1)) + end + N = sparse(N, ndofs, ndofs) + T = sparse(T, ndofs, ndofs) + gn = -N*B*(X+u) + gt = -T*B*(X+u) +# gn = -N*B*u + lan = N*la + lat = T*la + cn = 1.0e3 + C = lan - max(0, lan - cn*gn) + lat + # C = lan - gn + lat - gt <-- ihan viturallensa + # C = gn+gt <-- not working + # C = B*(X+u) + # C = B*u <- pitää kiinni, "tie". + # C = N*B*u + T*la <- palikat menee väärään suuntaan + # C = -N*B*(X+u) + T*la <- toimii suht hyvin mut kääntyy väärään suuntaan (t-suunnassa) + # C = -N*B*(X+u) - T*la <- sama + # C = -N*B*(X+u) - T*B*la <- sama + # C = N*la + T*la - max(0, N*la + N*B*(X+u)) + cond = lan[1:field_dim:end] - cn*gn[1:field_dim:end] + all_nodes = slave_element_nodes + inactive_nodes = find(cond .<= 0) + active_nodes = find(cond .> 0) + inactive_nodes = setdiff(all_nodes, inactive_nodes) + active_nodes = setdiff(all_nodes, active_nodes) + info("S = $all_nodes, I = $inactive_nodes, A = $active_nodes") + info("lambda = $(ForwardDiff.get_value(lan[slave_dofs]))") + info("gn = $(ForwardDiff.get_value(gn[slave_dofs]))") + #for j in active_nodes + # dofs = [field_dim*(j-1)+1, field_dim*(j-1)+2] + # C[dofs] = 0 + #end + +# C = -(N+T)*B*(X+u) +# C = -B*(X+u) + + return [fc; C] + + end + + A, allresults = ForwardDiff.jacobian(calculate_contact_rhs, x, ForwardDiff.AllResults) + b = -ForwardDiff.value(allresults) + A = sparse(A) + b = sparse(b) + K = A[1:ndofs,1:ndofs] + C1 = A[1:ndofs,ndofs+1:end]' + C2 = A[ndofs+1:end,1:ndofs] + D = A[ndofs+1:end,ndofs+1:end] + f = b[1:ndofs] + g = b[ndofs+1:end] + C2[2:field_dim:end] = 0 + g[2:field_dim:end] = 0 + +# C2[2:field_dim:end] = 0 +# g[2:field_dim:end] = 0 +# inactives = find(g[1:field_dim:end] .<= 0) +# actives = find(g[1:field_dim:end] .> 0) +# inactives = setdiff(slave_element_nodes, inactives) +# actives = setdiff(slave_element_nodes, actives) +# info("all nodes = $slave_element_nodes, inactives = $inactives, actives = $actives") +# info("g = $g") + +# for j in inactives + # dofs = [field_dim*(j-1)+1, field_dim*(j-1)+2] + # K[dofs,:] = 0 + # C1[dofs,:] = 0 + # C2[dofs,:] = 0 + # D[dofs,:] = 0 + # g[dofs,:] = 0 + #end + #for j in actives + # dofs = [field_dim*(j-1)+1, field_dim*(j-1)+2] + # C2[dofs[1],:] = 0 + #end + add!(assembly.K, K) + add!(assembly.C1, C1) + add!(assembly.C2, C2) + add!(assembly.D, D) + add!(assembly.f, f) + add!(assembly.g, g) +end + + +function assemble!{E<:MortarElements2D}(assembly::Assembly, + problem::Problem{Mortar}, slave_element::Element{E}, + time::Real, ::Type{Val{:forwarddiff_old2}}) + haskey(slave_element, "master elements") || return + props = problem.properties + field_dim = get_unknown_field_dimension(problem) + field_name = get_parent_field_name(problem) + + function calculate_interface(x::Vector) + + ndofs = round(Int, length(x)/2) + nnodes = round(Int, ndofs/field_dim) + u = reshape(x[1:ndofs], field_dim, nnodes) + la = reshape(x[ndofs+1:end], field_dim, nnodes) + fc = zeros(u) + C = zeros(la) + + slave_element_nodes = get_connectivity(slave_element) + X1 = slave_element("geometry", time) + u1 = Field(Vector[u[:,i] for i in slave_element_nodes]) + la1 = Field(Vector[la[:,i] for i in slave_element_nodes]) + x1 = X1 + u1 + + # 1. update nodal normals for this element. average nodes from adjacent elements + adjacent_elements = find_elements(get_elements(problem), slave_element_nodes) + adjacent_nodes = get_nodes(adjacent_elements) # including also nodes from adjacent elements + Q = [0.0 -1.0; 1.0 0.0] + normals = zeros(u) + for element in adjacent_elements + conn = get_connectivity(element) + gdofs = get_gdofs(element, field_dim) + X_el = element("geometry", time) + u_el = Field(Vector[u[:, i] for i in conn]) + x_el = X_el + u_el + for ip in get_integration_points(element, Val{3}) + dN = get_dbasis(element, ip) + N = element(ip, time) + t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)]) + normals[:, conn] += ip.weight*Q*t'*N + end + end + # --> slave side normals in deformed state + n1 = Field(Vector[normals[:,i]/norm(normals[:,i]) for i in slave_element_nodes]) + + for master_element in slave_element["master elements"] + + master_element_nodes = get_connectivity(master_element) + X2 = master_element("geometry", time) + u2 = Field(Vector[u[:,i] for i in master_element_nodes]) + x2 = X2 + u2 + + # calculate segmentation: we care only about endpoints + # note: these are quadratic/cubic functions, analytical solution possible + xi1a = project_from_master_to_slave(slave_element, x1, n1, x2[1]) + xi1b = project_from_master_to_slave(slave_element, x1, n1, x2[end]) + xi1 = clamp([xi1a; xi1b], -1.0, 1.0) + l = 1/2*abs(xi1[2]-xi1[1]) + isapprox(l, 0.0) && continue # no contribution in this master element + + nnodes = size(slave_element, 2) + De = zeros(nnodes, nnodes) + Me = zeros(nnodes, nnodes) + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = get_basis(slave_element, xi_s) + De += w*diagm(vec(N1)) + Me += w*N1'*N1 + end + Ae = De*inv(Me) + + slave_dofs = get_gdofs(slave_element, field_dim) + master_dofs = get_gdofs(master_element, field_dim) + + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + + # project gauss point from slave element to master element + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = vec(get_basis(slave_element, xi_s)) + x_s = N1*x1 # coordinate in gauss point + n_s = N1*n1 # normal direction in gauss point + t_s = Q'*n_s # tangent direction in gauss point + R_s = [n_s t_s] + xi_m = project_from_slave_to_master(master_element, x_s, n_s, x2) + N2 = vec(get_basis(master_element, xi_m)) + x_m = N2*x2 + Phi = Ae*N1 + + u_s = N1*u1 + u_m = N2*u2 + + la_s = Phi*la1 # traction force in gauss point + #lan = dot(n_s, la_s) # normal component + #lat = dot(t_s, la_s) # tangential component + la_nt = R_s*la_s + g = x_s-x_m + gn = props.gap_sign*dot(n_s, g) # normal gap + #gu = dot(n_s, u_s - u_m) # normal displacement gap + #gt = dot(t_s, x_s - x_m) # tangential gap + + fc[:,slave_element_nodes] += w*la_s*N1' + fc[:,master_element_nodes] -= w*la_s*N2' + C[1,slave_element_nodes] += w*gn*Phi' + #C[2,slave_element_nodes] += w*la_nt[2]*Phi' + #C[2,slave_element_nodes] += w*la_nt[2,:]*Phi' + #C[2,slave_element_nodes] += w*dot(t_s, u_s - u_m)*Phi' # <-- for tie + + #R += w*R_s + + end + + end # master elements done + + for (i, j) in enumerate(slave_element_nodes) + n = n1[i] + t = Q'*n + R = [n t] + la_nt = R*la[:,j] + C[2,j] += la_nt[2] + end + + return vec([fc C]) + + end + + # x doesn't mean deformed configuration here + x = [problem.assembly.u; problem.assembly.la] + ndofs = round(Int, length(x)/2) + #if ndofs == 0 + # info("INITIALIZING THINGS") + # problem.assembly.u = zeros(16) + # problem.assembly.la = zeros(16) + # x = [problem.assembly.u; problem.assembly.la] + # ndofs = round(Int, length(x)/2) + #end + + A, allresults = ForwardDiff.jacobian(calculate_interface, x, ForwardDiff.AllResults) + b = -ForwardDiff.value(allresults) + #b = -calculate_interface(x) + #info("PE = $(ForwardDiff.value(allresults))") + A = sparse(A) + b = sparse(b) + SparseMatrix.droptol!(A, 1.0e-12) + SparseMatrix.droptol!(b, 1.0e-12) + #println(A) + K = A[1:ndofs,1:ndofs] + C1 = transpose(A[1:ndofs,ndofs+1:end]) + C2 = A[ndofs+1:end,1:ndofs] + D = A[ndofs+1:end,ndofs+1:end] + f = b[1:ndofs] + g = b[ndofs+1:end] + add!(assembly.K, K) + add!(assembly.C1, C1) + add!(assembly.C2, C2) + add!(assembly.D, D) + add!(assembly.f, f) + add!(assembly.g, g) + + return + +end + + +function assemble!{E<:MortarElements2D}(assembly::Assembly, + problem::Problem{Mortar}, slave_element::Element{E}, + time::Real, ::Type{Val{:forwarddiff}}) + haskey(slave_element, "master elements") || return + props = problem.properties + field_dim = get_unknown_field_dimension(problem) + field_name = get_parent_field_name(problem) + + function calculate_interface(x::Vector) + + ndofs = round(Int, length(x)/2) + nnodes = round(Int, ndofs/field_dim) + u = reshape(x[1:ndofs], field_dim, nnodes) + la = reshape(x[ndofs+1:end], field_dim, nnodes) + fc = zeros(u) + C = zeros(la) + + slave_element_nodes = get_connectivity(slave_element) + X1 = slave_element("geometry", time) + u1 = Field(Vector[u[:,i] for i in slave_element_nodes]) + la1 = Field(Vector[la[:,i] for i in slave_element_nodes]) + x1 = X1 + u1 + + # 1. update nodal normals for this element. average nodes from adjacent elements + adjacent_elements = find_elements(get_elements(problem), slave_element_nodes) + adjacent_nodes = get_nodes(adjacent_elements) # including also nodes from adjacent elements + Q = [0.0 -1.0; 1.0 0.0] + normals = zeros(u) + for element in adjacent_elements + conn = get_connectivity(element) + gdofs = get_gdofs(element, field_dim) + X_el = element("geometry", time) + u_el = Field(Vector[u[:, i] for i in conn]) + x_el = X_el + u_el + for ip in get_integration_points(element, Val{3}) + dN = get_dbasis(element, ip) + N = element(ip, time) + t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)]) + normals[:, conn] += ip.weight*Q*t'*N + end + end + # --> slave side normals in deformed state + n1 = Field(Vector[ForwardDiff.get_value(normals[:,i]/norm(normals[:,i])) for i in slave_element_nodes]) + + + nnodes = size(slave_element, 2) + lan_tot = zeros(nnodes) # normal pressure + gap_tot = zeros(nnodes) # weighted normal gap + + for master_element in slave_element["master elements"] + + master_element_nodes = get_connectivity(master_element) + X2 = master_element("geometry", time) + u2 = Field(Vector[u[:,i] for i in master_element_nodes]) + x2 = X2 + u2 + + # calculate segmentation: we care only about endpoints + # note: these are quadratic/cubic functions, analytical solution possible + xi1a = project_from_master_to_slave(slave_element, x1, n1, x2[1]) + xi1b = project_from_master_to_slave(slave_element, x1, n1, x2[end]) + xi1 = clamp([xi1a; xi1b], -1.0, 1.0) + l = 1/2*abs(xi1[2]-xi1[1]) + isapprox(l, 0.0) && continue # no contribution in this master element + + De = zeros(nnodes, nnodes) + Me = zeros(nnodes, nnodes) + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = get_basis(slave_element, xi_s) + De += w*diagm(vec(N1)) + Me += w*N1'*N1 + end + Ae = De*inv(Me) + + slave_dofs = get_gdofs(slave_element, field_dim) + master_dofs = get_gdofs(master_element, field_dim) + + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + + # project gauss point from slave element to master element + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = vec(get_basis(slave_element, xi_s)) + x_s = N1*x1 # coordinate in gauss point + n_s = N1*n1 # normal direction in gauss point + t_s = Q'*n_s # tangent direction in gauss point + R_s = [n_s t_s] + xi_m = project_from_slave_to_master(master_element, x_s, n_s, x2) + N2 = vec(get_basis(master_element, xi_m)) + x_m = N2*x2 + Phi = Ae*N1 + + u_s = N1*u1 + u_m = N2*u2 + + la_s = Phi*la1 # traction force in gauss point + la_nt = R_s*la_s + gn = -dot(n_s, x_s - x_m) # normal gap + + fc[:,slave_element_nodes] += w*la_s*N1' + fc[:,master_element_nodes] -= w*la_s*N2' + #C[1,slave_element_nodes] += w*gn*Phi' + + lan_tot += w*la_nt[1]*Phi + gap_tot += w*gn*Phi + + end + + end # master elements done + +# ncf = lan_tot - max(0, lan_tot - gap_tot) +# info("pressure in nodes: $(ForwardDiff.get_value(lan_tot))") +# info("weighted gap in nodes: $(ForwardDiff.get_value(gap_tot))") +# info("ncf: $(ForwardDiff.get_value(ncf))") +# cond = +lan_tot + gap_tot +# cond = +lan_tot - gap_tot # singular +# cond = -lan_tot + gap_tot +# cond = -lan_tot - gap_tot + + for (i, j) in enumerate(slave_element_nodes) + n = n1[i] + t = Q'*n + R = [n t] + la_nt = R*la[:,j] + info("node $j, n=$(ForwardDiff.get_value(n)) lan = $(ForwardDiff.get_value(la_nt[1])) gap = $(ForwardDiff.get_value(gap_tot[i]))") + +# if -lan_tot[i] + gap_tot[i] < 0 + if -la_nt[1] + gap_tot[i] < 0 + #if j in [31, 32, 33, 34, 35, 36] + info("set node $j active") + C[1,j] -= gap_tot[i] +# C[1,j] += la_nt[1] - max(0, la_nt[1] - gap_tot[i]) + C[2,j] += la_nt[2] + else + info("set node $j inactive") + C[1,j] += la1[i][1] + C[2,j] += la1[i][2] + end + end + + return vec([fc C]) + + end + + # x doesn't mean deformed configuration here + x = [problem.assembly.u; problem.assembly.la] + ndofs = round(Int, length(x)/2) + A, allresults = ForwardDiff.jacobian(calculate_interface, x, ForwardDiff.AllResults) + b = -ForwardDiff.value(allresults) + #b = -calculate_interface(x) + #info("PE = $(ForwardDiff.value(allresults))") + A = sparse(A) + b = sparse(b) + SparseMatrix.droptol!(A, 1.0e-12) + SparseMatrix.droptol!(b, 1.0e-12) + #println(A) + K = A[1:ndofs,1:ndofs] + C1 = transpose(A[1:ndofs,ndofs+1:end]) + C2 = A[ndofs+1:end,1:ndofs] + D = A[ndofs+1:end,ndofs+1:end] + f = b[1:ndofs] + g = b[ndofs+1:end] + add!(assembly.K, K) + add!(assembly.C1, C1) + add!(assembly.C2, C2) + add!(assembly.D, D) + add!(assembly.f, f) + add!(assembly.g, g) + + return + +end + diff --git a/src/mortar_3d.jl b/src/mortar_3d.jl new file mode 100644 index 0000000..b4194e4 --- /dev/null +++ b/src/mortar_3d.jl @@ -0,0 +1,643 @@ +# This file is a part of JuliaFEM. +# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md + +# Mortar projection calculation for 3d cases + +""" Construct auxiliary plane for surface. """ +function create_auxiliary_plane{E}(element::Element{E}, time::Real) + xi = get_reference_element_midpoint(E) + x0 = element("geometry", xi, time) + ntbasis = element("normal-tangential coordinates", xi, time) + return x0, ntbasis +end + + +""" +Project point q onto a plane given by a point p and normal n. + +Parameters +---------- +q::Array{Float64, 2} + point to project (row vector) +x0::Array{Float64, 2} + origo of plane +n::Array{Float64, 2} + normal vector of plane + +Returns +------- +y::Array{Float64, 2} + projected point + +Examples +-------- +julia> p = [-0.5 -1.0 4.0]' +julia> x0 = [0.0 0.075 0.675]' +julia> n = [0.1485860 0.0784519 0.9857830]' +julia> project_node_to_auxiliary_plane(p, x0, n) +3-element Array{Float64,1}: + 0.963455 + -1.2447 + 0.925247 + +Notes +----- +[1](http://stackoverflow.com/questions/8942950/how-do-i-find-the-orthogonal-projection-of-a-point-onto-a-plane) + +""" +function project_point_to_auxiliary_plane(p::Vector, x0::Vector, Q::Matrix) + n = Q[:,1] + ph = p - dot(p-x0, n)*n + qproj = Q'*(ph-x0) + if !isapprox(qproj[1], 0.0; atol=1.0e-12) + info("project_point_to_auxiliary_plane(): point not projected correctly.") + info("p: $p") + info("x0: $x0") + info("Q: \n$Q") + info("qproj: $qproj") + error("Failed to project point to auxiliary plane.") + end + return qproj[2:3] +end + +""" +Find edge intersections of two planar arbitrary shape polygons. + +Parameters +---------- +S::Array{Float64,2} +M::Array{Float64,2} + +Matrices with size (2, n) where n is number of vertices of each polygon. + +Returns +------- +P::Array{Float64,2} + Intersection points of polygons +n::Array{Float64,2} + Neighbour info matrix with size (ns, mn). This keeps information which + edges of polygons are intersecting. See further explanation in example + below. + +Examples +-------- +Find intersection points of two triangles: + +julia> S = [0 0; 3 0; 0 3]' +julia> M = [-1 1; 2 -1/2; 1 3/2]' +julia> P, n = get_edge_intersections(S, M) +julia> P +2x4 Array{Float64,2}: + 1.0 1.75 0.0 0.0 + 0.0 0.0 0.5 1.25 +julia> n +3x3 Array{Int64,2}: + 1 1 0 + 0 0 0 + 1 0 1) + +So intersection points are: (1.00, 0.00), (1.75, 0.00), (0.00, 0.50), (0.00, 1.25). +"Neighbour matrix" can be interpreted as following: + + 1 1 0 <--> First edge of S intersects edges 1 and 2 of M + 0 0 0 <--> Second edge of S doesn't intersect at all + 1 0 1 <--> Third edge of S intersects with edges 1 and 3 of M + +""" +function get_edge_intersections(S::Matrix, M::Matrix) + ns = size(S, 2) + nm = size(M, 2) + P = zeros(2, 0) + n = zeros(Int64, ns, nm) + k = 0 + for i=1:ns + for j=1:nm + b = M[:,j]-S[:,i] + A = [S[:,mod(i,ns)+1]-S[:,i] -M[:,mod(j,nm)+1]+M[:,j]] + if rank(A) == 2 + r = A\b + if (r[1]>=0) & (r[1]<=1) & (r[2]>=0) & (r[2]<=1) # intersection found + k += 1 + f = S[:,i]+r[1]*(S[:,mod(i,ns)+1] - S[:,i]) + f = f'' + P = hcat(P, f) + n[i, j] = 1 + end + end + end + end + return P, n +end + + +""" +Find any points laying inside or border of triangle. + +Parameters +---------- +Y::Array{Float64, 2} + Triangle coordinates in 2×3 matrix +X::Array{Float64, 2} + List of points to test in 2×n matrix + +Returns +------- +P::Array{Float64, 2} + List of points in triangle in 2×m matrix, where m is number of points inside triangle + +Examples +-------- +julia> S = [0.0 0.0; 3.0 0.0; 0.0 3.0]' # triangle corner points +julia> pts = [-1.0 1.0; 2.0 -0.5; 1.0 1.5; 0.5 1.5]' # points to tests +julia> points_in_triangle(S, pts) +2x2 Array{Float64,2}: + 1.0 0.5 + 1.5 1.5 +""" +function get_points_inside_triangle(Y::Matrix, X::Matrix) + @assert size(Y, 2) == 3 # "Point in TRIANGLE..." + P = zeros(2, 0) + v0 = Y[:,2] - Y[:,1] + v1 = Y[:,3] - Y[:,1] # find interior points of X in Y + d00 = (v0'*v0)[1] + d01 = (v0'*v1)[1] + d11 = (v1'*v1)[1] # using baricentric coordinates + id = 1/(d00*d11 - d01*d01) + for i=1:size(X, 2) + v2 = X[:,i] - Y[:,1] + d02 = (v0'*v2)[1] + d12 = (v1'*v2)[1] + u = (d11*d02-d01*d12)*id + v = (d00*d12-d01*d02)*id + if (u>=0) & (v>=0) & (u+v<=1) # also include nodes on the boundary + P = hcat(P, X[:,i]'') + end + end + return P +end + +""" +Determine is point P inside or on boudary of polygon X. + +http://paulbourke.net/geometry/polygonmesh/#insidepoly +""" +function is_point_inside_convex_polygon(P, X) + x, y = P + for i=1:length(X) + x0, y0 = X[i] + x1, y1 = X[mod(i, length(X))+1] + if (y-y0)*(x1-x0) - (x-x0)*(y1-y0) < 0 + return false + end + end + return true +end + +function get_points_inside_convex_polygon(pts, X) + # TODO: Make more readable + X2 = [X[:,i] for i=1:size(X,2)] + c = filter(P->is_point_inside_convex_polygon(P, X2), [pts[:,i] for i=1:size(pts, 2)]) + return length(c) == 0 ? zeros(2, 0) : hcat(c...) +end + +""" Return unique objects with some given tolerance. This is used in next function + because traditional unique() command returns row vectors as non-unique if they + differs only a "little". +""" +function uniquetol(P, dim::Int; args...) + @assert dim == 2 + items = Vector{Float64}[P[:,i] for i=1:size(P,dim)] + new_items = Vector{Float64}[] + for item in items + has_found = false + for new_item in new_items + if isapprox(item, new_item; args...) + has_found = true + break + end + end + if !has_found + push!(new_items, item) + end + end + return reshape([new_items...;], length(new_items[]), length(new_items)) +end + + +""" +Make polygon clipping of shapes S and M. + +Parameters +---------- +S::Array{Float64, 2} +M::Array{Float64, 2} + Shapes to clip. Needs to be triangles at the moment. + +Returns +------- +Array{Float64, 2}, Array{Float64, 2} +- Polygon vertices in 2×n matrix, sorted in counter-clockwise order. +- 3×3 "neighbouring" matrix, see example. + +Examples +-------- +julia> S = [0 0; 3 0; 0 3]' +julia> M = [-1 1; 2 -1/2; 2 2]' +julia> P, n = clip_polygon(S, M) +julia> P +2x6 Array{Float64,2}: + 0.0 1.0 2.0 2.0 1.25 0.0 + 0.5 0.0 0.0 1.0 1.75 1.33333, +julia> n +3x3 Array{Int64,2}: + 1 0 1 <- first edge of M ([-1 1; 2 -1/2]') intersects with edges 1 and 3 of S ([0 0; 3 0]' and [0 3; 0 0]') + 1 1 0 <- second edge of M ([2 -1/2; 2 2]') intersects with edges 1 and 2 of S + 0 1 1 <- third edge of M ([2 2; -1 1]') intersects with edgse 2 and 3 of S + +""" +function clip_polygon(S::Matrix, M::Matrix) + P1, neighbours = get_edge_intersections(M, S) + #P2 = get_points_inside_triangle(M, S) + #P3 = get_points_inside_triangle(S, M) + P2 = get_points_inside_convex_polygon(M, S) + P3 = get_points_inside_convex_polygon(S, M) +# info("polygon clipping: P1 = $P1") +# info("polygon clipping: P2 = $P2") +# info("polygon clipping: P3 = $P3") +# info("hcat P = $P") + P = hcat(P1, P2, P3) + if length(P) == 0 + return nothing, nothing + end + P = uniquetol(P, 2) + meanval = mean(P, 2) + tmp = P .- meanval + angles = atan2(tmp[2,:], tmp[1,:]) + angles = reshape(angles, length(angles)) + order = sortperm(angles) + return P[:, order], neighbours +end + + +""" +Calculate polygon geometric center point + +Parameters +---------- +P::Array{Float64, 2} + Polygon vertices in 2×n matrix + +Returns +------- +Array{Float63, 2} + Center point + +Examples +-------- +julia> P +2x6 Array{Float64,2}: + 0.0 1.0 2.0 2.0 1.25 0.0 + 0.5 0.0 0.0 1.0 1.75 1.33333, +julia> C = get_polygon_cp(P) +2x1 Array{Float64,2}: + 1.039740 + 0.804701 + +""" +function calculate_polygon_centerpoint(P::Matrix) + n = size(P, 2) + A = 0.0 + for i=1:n + A += 1/2*(P[1,i]*P[2,mod(i,n)+1] - P[1,mod(i,n)+1]*P[2,i]) + end + Cx = 0.0 + Cy = 0.0 + for i=1:n + inext = mod(i, n)+1 + Cx += 1/(6*A)*(P[1,i] + P[1,inext])*(P[1,i]*P[2,inext] - P[1,inext]*P[2,i]) + Cy += 1/(6*A)*(P[2,i] + P[2,inext])*(P[1,i]*P[2,inext] - P[1,inext]*P[2,i]) + end + return Float64[Cx, Cy] +end + +""" +Project point from auxiliary plane to parametric surface given by (ξ₁, ξ₂) + +Parameters +---------- +p::Array{Float64,1} + point in auxiliary plane, in (n,t1,t2) coordinate system +x0::Array{Float64,1} + origo of auxiliary plane cs +Q::Array{Float64,2} + basis of auxiliary plane cs +x::Array{Float64,2} + surface node coords +basis::Array{Float64,2} + surface basis functions +dbasis::Array{Float64,2} + partial derivatives of surface basis functions + +Returns +------- +Array{Float64,2} + solution vector (d, ξ₁, ξ₂) where d is distance to surface + +Examples +-------- +Define surface with node points, basis + dbasis + +julia> xquad = [ +... -2.5 -2.0 1.0 +... 2.5 -2.0 0.7 +... 2.0 2.3 0.0 +... -2.0 2.0 1.0]' +julia> basis(xi) = [ +... (1-xi[1])(1-xi[2])/4 +... (1+xi[1])(1-xi[2])/4 +... (1+xi[1])(1+xi[2])/4 +... (1-xi[1])(1+xi[2])/4] +julia> dbasis(xi) = [ +... -(1-xi[2])/4 -(1-xi[1])/4 +... (1-xi[2])/4 -(1+xi[1])/4 +... (1+xi[2])/4 (1+xi[1])/4 +... -(1+xi[2])/4 (1-xi[1])/4] + +We aim to find point p, which we first project to auxiliary plane defined as following +julia> p = [-2.5 -2.0 1.0]' +julia> x0 = [0.0 0.075 0.675]' +julia> Q = [ +... 0.1485860 0.9888990 0.0000000 +... 0.0784519 -0.0117877 0.9968480 +... 0.9857830 -0.1481180 -0.0793325] + +Our projected point is therefore +julia> n = Q[:,1] # first component is normal direction +julia> ph = project_node_to_auxiliary_plane(p, x0, n) +julia> ph = Q'(ph-x0) +julia> ph +3x1 Array{Float64,2}: + 1.33264e-7 + -2.49593 + -2.09424 + +Our point ph is now in auxiliary plane in n,t1,t2 coordinate system. Next we +project it back to surface defined by xquad*basis + +julia> theta = project_point_from_plane_to_surface(ph, x0, Q, xquad, basis, dbasis) +julia> theta +3x1 Array{Float64,2}: + -0.213874 + -0.999999 + -1.0 + +We see that our ξ₁ = ξ₂ = -1 so we found first point of xquad +[-2.5 -2.0 1.0]' correctly. + +julia> xquad*basis(theta[2:3]) +3-element Array{Float64,1}: + -2.5 + -2.0 + 1.0 + +""" +function project_point_from_plane_to_surface{E}(p::Vector, x0::Vector, Q::Matrix, element::Element{E}, time::Real; max_iterations::Int=10, iter_tol::Float64=1.0e-9) + basis(xi) = get_basis(E, xi) + dbasis(xi) = get_dbasis(E, xi) + x = element("geometry", time) + ph = Q*[0; p] + x0 + theta = Float64[0.0, 0.0, 0.0] + n = Q[:,1] + for i=1:max_iterations + b = ph + theta[1]*n - basis(theta[2:3])*x + J = [n -dbasis(theta[2:3])*x] + dtheta = J \ -b + theta += dtheta + if norm(dtheta) < iter_tol + return theta + end + end + begin + info("projecting point from auxiliary plane back to surface didn't go very well.") + info("element type: $E") + info("element connectivity: $(get_connectivity(element))") + info("auxiliary plane: x0 = $x0, Q = $Q") + info("point coordinates on plane: $p") + info("element geometry: $x") + info("ph: $ph") + info("normal direction: $n") + info("parameter vector before giving up: $theta") + end + error("project_point_to_surface: did not converge in $max_iterations iterations!") +end + +typealias MortarElements3D Union{Tri3, Quad4} + +function assemble!{E<:MortarElements3D}(assembly::Assembly, problem::Problem{Mortar}, + slave_element::Element{E}, time::Real, ::Type{Val{:total}}) + assemble!(assembly, problem, slave_element, time, Val{problem.properties.formulation}) +end + +function assemble!{E<:MortarElements3D}(assembly::Assembly, problem::Problem{Mortar}, + slave_element::Element{E}, time::Real, ::Type{Val{:total}}) + haskey(slave_element, "master elements") || return + field_dim = get_unknown_field_dimension(problem) + field_name = get_parent_field_name(problem) + slave_dofs = get_gdofs(slave_element, field_dim) + + props = problem.properties + if props.formulation == :Standard && props.normal_condition == :Contact + error("for contact choose Dual formulation.""") + end + + # create auxiliary plane and project slave nodes to it + # x0 = origo, Q = local basis + x0, Q = create_auxiliary_plane(slave_element, time) + + # 1. project slave nodes to auxiliary plane + Sl = Vector{Float64}[] + for p in slave_element("geometry", time) + push!(Sl, project_point_to_auxiliary_plane(p, x0, Q)) + end + S = hcat(Sl...) + + for master_element in slave_element["master elements"] + + # if distance between elements is "far enough" cannot expect contact + if (props.normal_condition == :Contact) || props.inequality_constraints + slave_midpoint = slave_element("geometry", [0.0, 0.0], time) + master_midpoint = master_element("geometry", [0.0, 0.0], time) + if norm(slave_midpoint - master_midpoint) > props.minimum_distance + continue + end + end + + master_dofs = get_gdofs(master_element, field_dim) + + # 2. project master nodes to auxiliary plane + M = Vector{Float64}[] + for p in master_element("geometry", time) + push!(M, project_point_to_auxiliary_plane(p, x0, Q)) + end + M = hcat(M...) + + # 3. create polygon clipping on auxiliary plane + P = nothing + neighbours = nothing + try + P, neighbours = clip_polygon(S, M) + catch + info("polygon clipping failed") + info("S = ") + dump(S) + info("M = ") + dump(M) + info("original Sl = ") + info(Sl) + error("cannot continue") + end + isa(P, Void) && continue # no clipping + + # shared edge but no shared volume. skipping + size(P, 2) < 3 && continue + + C = calculate_polygon_centerpoint(P) + npts = size(P, 2) # number of vertices in polygon + + # loop vertices and create temporary integrate cells + # TODO: basically when npts == 3 or npts == 4 we could integrate without splitting to cells. + nnodes = size(slave_element, 2) + C1S3 = zeros(3*nnodes, 3*nnodes) + C1M3 = zeros(3*nnodes, 3*nnodes) + + for pnt=1:npts # integration of mortar matrices begin + cell = Field(Vector{Float64}[C, P[:,pnt], P[:,mod(pnt,npts)+1]]) + + # calculate slave side projection matrix D + # construct dual basis + Ae = zeros(nnodes, nnodes) + De = zeros(nnodes, nnodes) + Me = zeros(nnodes, nnodes) + if problem.properties.formulation == :Dual # Construct dual basis + for ip in get_integration_points(Tri3, Val{5}) + N = get_basis(Tri3, ip.xi) + xi = vec(N*cell) + theta = project_point_from_plane_to_surface(xi, x0, Q, slave_element, time) + xi_slave = theta[2:3] + N1 = slave_element(xi_slave, time) + # jacobian determinant on integration cell + dNC = get_dbasis(Tri3, ip.xi) + JC = sum([kron(dNC[:,j], cell[j]') for j=1:length(cell)]) + wC = ip.weight*det(JC) + De += wC*diagm(vec(N1)) + Me += wC*N1'*N1 + end + Ae = De*inv(Me) + end + for i=1:field_dim + C1S3[i:field_dim:end,i:field_dim:end] += De + end + + # Calculate master side projection matrix M + for ip in get_integration_points(Tri3, Val{5}) + # gauss point in auxiliary plane + #N = get_basis(E, ip.xi) + N = get_basis(Tri3, ip.xi) + xi = vec(N*cell) # xi defined in auxilary plane + + # find projection of gauss point to master and slave elements + theta1 = project_point_from_plane_to_surface(xi, x0, Q, slave_element, time) + theta2 = project_point_from_plane_to_surface(xi, x0, Q, master_element, time) + xi_slave = theta1[2:3] + xi_master = theta2[2:3] + + # evaluate shape functions values in gauss point and add contribution to matrices + N1 = slave_element(xi_slave, time) + N2 = master_element(xi_master, time) + + # jacobian determinant on integration cell + dNC = get_dbasis(Tri3, ip.xi) + JC = sum([kron(dNC[:,j], cell[j]') for j=1:length(cell)]) + wC = ip.weight*det(JC) + + # extend matrices according to the problem dimension (3) + @assert length(slave_dofs) == length(master_dofs) + Me = wC*Ae*N1'*N2 + for k=1:field_dim + C1M3[k:field_dim:end,k:field_dim:end] += Me + end + end + end # integration of mortar matrices done. + + # constraints in normal-tangential direction and initial weighted gap + X1 = vec(slave_element("geometry", time)) + X2 = vec(master_element("geometry", time)) + Q_ = slave_element("normal-tangential coordinates", time) + Z = zeros(3, 3) + if nnodes == 3 + Q3 = [Q Z Z; Z Q Z; Z Z Q] + elseif nnodes == 4 + Q3 = [Q Z Z Z; Z Q Z Z; Z Z Q Z; Z Z Z Q] + end + D3 = zeros(3*nnodes, 3*nnodes) + C2S3 = Q3'*C1S3 + C2M3 = Q3'*C1M3 + G = -(C2S3*X1 - C2M3*X2) + + # complementarity condition + if haskey(slave_element, "displacement") + u1 = vec(slave_element("displacement", time)) + else + u1 = zeros(3*nnodes) + end + if haskey(master_element, "displacement") + u2 = vec(master_element("displacement", time)) + else + u2 = zeros(3*nnodes) + end + x1 = X1 + u1 + x2 = X2 + u2 + if haskey(slave_element, "reaction force") + la = vec(slave_element("reaction force", time)) + else + la = zeros(3*nnodes) + end + g = -(C2S3*x1 - C2M3*x2) + c = Q3'*la - g + inactive_nodes = find(c[1:field_dim:end] .<= 0) + active_nodes = find(c[1:field_dim:end] .> 0) + + # normal constraint: remove inactive nodes if normal condition is set to contact + if problem.properties.normal_condition == :Contact + for j in inactive_nodes + dofs = [3*(j-1)+1, 3*(j-1)+2, 3*(j-1)+3] + G[dofs] = 0 + C1S3[dofs,:] = 0 + C1M3[dofs,:] = 0 + C2S3[dofs,:] = 0 + C2M3[dofs,:] = 0 + end + end + + # tangential constraint: stick or slip + if problem.properties.tangential_condition == :Slip + D3 = copy(C2S3) + D3[1:field_dim:end, :] = 0 + C2S3[2:field_dim:end, :] = 0 + C2M3[2:field_dim:end, :] = 0 + C2S3[3:field_dim:end, :] = 0 + C2M3[3:field_dim:end, :] = 0 + end + + # add contributions + add!(assembly.C1, slave_dofs, slave_dofs, C1S3) + add!(assembly.C1, slave_dofs, master_dofs, -C1M3) + add!(assembly.C2, slave_dofs, slave_dofs, C2S3) + add!(assembly.C2, slave_dofs, master_dofs, -C2M3) + add!(assembly.D, slave_dofs, slave_dofs, D3) + add!(assembly.c, slave_dofs, c) + add!(assembly.g, slave_dofs, G) + end +end + + diff --git a/src/mortar_forwarddiff_pe.jl b/src/mortar_forwarddiff_pe.jl new file mode 100644 index 0000000..f0117a8 --- /dev/null +++ b/src/mortar_forwarddiff_pe.jl @@ -0,0 +1,446 @@ +using JuliaFEM.Core: MortarElements2D, DVTI, Assembly + +import JuliaFEM.Core: project_from_master_to_slave, project_from_slave_to_master, assemble!, +get_unknown_field_dimension, get_parent_field_name, get_gdofs, find_elements, get_nodes, Field, +get_integration_points, get_basis, get_dbasis, add! + +""" Find segment from slave element corresponding to master element nodes. +x1_, n1_ +slave element geometry and normal direction + +x2_ master element nodes to project onto slave +""" +function project_from_master_to_slave{E<:MortarElements2D}( + slave_element::Element{E}, x1_::DVTI, n1_::DVTI, x2::Vector) + + function x1(xi1) + N = get_basis(E, xi1) + return vec(N)*x1_ + end + + function dx1(xi1) + dN = get_dbasis(E, xi1) + return vec(dN)*x1_ + end + + function n1(xi1) + N = get_basis(E, xi1) + return vec(N)*n1_ + end + + function dn1(xi1) + dN = get_dbasis(E, xi1) + return vec(dN)*n1_ + end + + cross2(a, b) = cross([a; 0], [b; 0])[3] + R(xi1) = cross2(x1(xi1)-x2, n1(xi1)) + dR(xi1) = cross2(dx1(xi1), n1(xi1)) + cross2(x1(xi1)-x2, dn1(xi1)) + xi1 = 0.0 + for i=1:5 + dxi1 = -R(xi1)/dR(xi1) + xi1 += dxi1 + if norm(dxi1) < 1.0e-10 + return xi1 + end + end + + error("find projection from master to slave: did not converge") + +end + +function project_from_slave_to_master{E<:MortarElements2D}( + master_element::Element{E}, x1::Vector, n1::Vector, x2_::DVTI) + + function x2(xi2) + N = get_basis(E, xi2) + return vec(N)*x2_ + end + + function dx2(xi2) + dN = get_dbasis(E, xi2) + return vec(dN)*x2_ + end + + cross2(a, b) = cross([a; 0], [b; 0])[3] + R(xi2) = cross2(x2(xi2)-x1, n1) + dR(xi2) = cross2(dx2(xi2), n1) + xi2 = 0.0 + dxi2 = 0.0 + for i=1:5 + dxi2 = -R(xi2) / dR(xi2) + xi2 += dxi2 + if norm(dxi2) < 1.0e-10 + return xi2 + end + end + + error("find projection from slave to master: did not converge, last val: $xi2 and $dxi2") + +end + + +function assemble!{E<:MortarElements2D}(assembly::Assembly, + problem::Problem{Mortar}, slave_element::Element{E}, + time::Real, ::Type{Val{:forwarddiff}}) + haskey(slave_element, "master elements") || return + props = problem.properties + field_dim = get_unknown_field_dimension(problem) + field_name = get_parent_field_name(problem) + + function calculate_interface(u::Matrix, la::Matrix) + + X1 = slave_element("geometry", time) + slave_element_nodes = get_connectivity(slave_element) + u1 = Field(Vector[u[:,i] for i in slave_element_nodes]) + la1 = Field(Vector[la[:,i] for i in slave_element_nodes]) + x1 = X1 + u1 + + adjacent_elements = find_elements(get_elements(problem), slave_element_nodes) + adjacent_nodes = get_nodes(adjacent_elements) # including also nodes from adjacent elements + Q = [0.0 -1.0; 1.0 0.0] + # 1. update nodal normals for this element + normals = zeros(u) + for element in adjacent_elements + conn = get_connectivity(element) + gdofs = get_gdofs(element, field_dim) + X_el = element("geometry", time) + u_el = Field(Vector[u[:, i] for i in conn]) + x_el = X_el + u_el + for ip in get_integration_points(element, Val{3}) + dN = get_dbasis(element, ip) + N = element(ip, time) + t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)]) + normals[:, conn] += ip.weight*Q*t'*N + end + end + # --> slave side normals in deformed state + n1 = Field(Vector[normals[:,i]/norm(normals[:,i]) for i in slave_element_nodes]) + + fc = SparseMatrixCOO{Real}([], [], []) # interface virtual work + C = SparseMatrixCOO{Real}([], [], []) # constraints + B = SparseMatrixCOO{Real}([], [], []) + + #info("u1.data = ", ForwardDiff.get_value(u1.data)) + info("normal calculations done. looping master elements.") + for master_element in slave_element["master elements"] + X2 = master_element("geometry", time) + master_element_nodes = get_connectivity(master_element) + u2 = Field(Vector[u[:,i] for i in master_element_nodes]) + x2 = X2 + u2 + info("master element ready.") + + # calculate segmentation: we care only about endpoints + # note: these are quadratic/cubic functions, analytical solution possible + info("calculating segmentation.") + xi1a = project_from_master_to_slave(slave_element, x1, n1, x2[1]) + xi1b = project_from_master_to_slave(slave_element, x1, n1, x2[end]) + xi1 = clamp([xi1a; xi1b], -1.0, 1.0) + l = 1/2*abs(xi1[2]-xi1[1]) + isapprox(l, 0.0) && continue # no contribution + info("xi1 = $xi1") + + info("create bi-orthogonal basis") + nnodes = size(slave_element, 2) + De = zeros(nnodes, nnodes) + Me = zeros(nnodes, nnodes) + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = get_basis(slave_element, xi_s) + De += w*diagm(vec(N1)) + Me += w*N1'*N1 + end + Ae = De*inv(Me) + info("bi-orthogonal basis done. integrating fc.") + + slave_dofs = get_gdofs(slave_element, field_dim) + master_dofs = get_gdofs(master_element, field_dim) + + info("integrate fc") + D = zeros(nnodes, nnodes) + M = zeros(nnodes, nnodes) + gn = zeros(nnodes) + lan = zeros(nnodes) + lat = zeros(nnodes) + + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = get_basis(slave_element, xi_s) + # project gauss point to master element to evaluate shape function there + x_s = vec(N1)*x1 # coordinate in gauss point + n_s = vec(N1)*n1 # normal direction in gauss point + xi_m = project_from_slave_to_master(master_element, x_s, n_s, x2) + N2 = get_basis(master_element, xi_m) + x_m = vec(N2)*x2 + Phi = vec(Ae*N1') + la_s = Phi*la1 # traction force in gauss point + u_s = vec(N1)*u1 + u_m = vec(N2)*u2 + #info("la_s = $(ForwardDiff.get_value(la_s))") + SM = [slave_dofs; master_dofs] + #N1N2 = [N1 -N2] + #info("all_dofs = $(SM)") + #info("shape functions = $(ForwardDiff.get_value(N1N2))") + #for i=1:field_dim + # #info("add to slave dofs $(slave_dofs[i:field_dim:end])") + # #info("add to master dofs $(master_dofs[i:field_dim:end])") + # add!(fc, slave_dofs[i:field_dim:end], [1, 1], -w*la_s[i]*N1) + # add!(fc, master_dofs[i:field_dim:end], [1, 1], +w*la_s[i]*N2) + #add!(fc, slave_dofs[i:field_dim:end], [1, 1], w*la_s'*u_s[i]) + #add!(fc, master_dofs[i:field_dim:end], [1, 1], -w*la_s'*u_m[i]) + # add!(fc, master_dofs[i:field_dim:end], [1, 1], -w*la_s[i]*u_m) + #end + #add!(fc, [slave_dofs; master_dofs], [1, 1, 1, 1, 1, 1, 1, 1], w*la_s*[u_s' -u_m']) + D += w*kron(Ae*N1', N1) + M += w*kron(Ae*N1', N2) + gn += -w*dot(n_s, x_s-x_m)*Phi + lan += w*dot(n_s, la_s)*Phi + t_s = Q'*n_s + lat += w*dot(t_s, la_s)*Phi + end + + #D2 = zeros(2*nnodes, 2*nnodes) + #M2 = zeros(2*nnodes, 2*nnodes) + #for i=1:field_dim + # D2[i:field_dim:end, i:field_dim:end] += D + # M2[i:field_dim:end, i:field_dim:end] += M + #end + #info("size of D2 = $(size(D2))") + #fco = [D2 -M2]*vec(la1) + #fco = [D -M]*la[:,slave_element_nodes] + #info("fco = $(ForwardDiff.get_value(fco))") + #add!(fc, [slave_dofs; master_dofs], [1, 1, 1, 1], fco) + + for i=1:field_dim + add!(B, slave_dofs[i:field_dim:end], slave_dofs[i:field_dim:end], D) + add!(B, slave_dofs[i:field_dim:end], master_dofs[i:field_dim:end], -M) + end + info("gn = $gn") + #Cj = lan - max(0, lan - gn) + lat + add!(C, slave_dofs[1:field_dim:end], [1, 1], gn') + + end # master elements done + + ndofs = prod(size(la)) + N = SparseMatrixCOO{Real}([], [], []) + T = SparseMatrixCOO{Real}([], [], []) + for (i, j) in enumerate(slave_element_nodes) + dofs = [2*(j-1)+1, 2*(j-1)+2] + add!(N, [dofs[1]], dofs, reshape(n1[i], 1, 2)) + add!(T, [dofs[2]], dofs, reshape(Q'*n1[i], 1, 2)) + end + N = sparse(N, ndofs, ndofs) + T = sparse(T, ndofs, ndofs) + B = sparse(B, ndofs, ndofs) + fc = B'*vec(la) + #println(sparse(fc)) + #fc = sparse(fc, ndofs, 1) + #println(fc) + #dump(full(fc)) + #C = sparse(C, ndofs, 1) + C = N*B*vec(u) + T*vec(la) + return fc, C + + end + + + function calculate_interface_PE(x::Vector) + + ndofs = round(Int, length(x)/2) + nnodes = round(Int, ndofs/field_dim) + u = reshape(x[1:ndofs], field_dim, nnodes) + la = reshape(x[ndofs+1:end], field_dim, nnodes) + #fixed_la = ForwardDiff.get_value(la) + #fixed_u = ForwardDiff.get_value(u) + #u = ForwardDiff.get_value(u) + + X1 = slave_element("geometry", time) + slave_element_nodes = get_connectivity(slave_element) + u1 = Field(Vector[u[:,i] for i in slave_element_nodes]) + la1 = Field(Vector[la[:,i] for i in slave_element_nodes]) + #fixed_la1 = Field(Vector[fixed_la[:,i] for i in slave_element_nodes]) + x1 = X1 + u1 + + # 1. update nodal normals for this element + adjacent_elements = find_elements(get_elements(problem), slave_element_nodes) + adjacent_nodes = get_nodes(adjacent_elements) # including also nodes from adjacent elements + Q = [0.0 -1.0; 1.0 0.0] + normals = zeros(u) + for element in adjacent_elements + conn = get_connectivity(element) + gdofs = get_gdofs(element, field_dim) + X_el = element("geometry", time) + u_el = Field(Vector[u[:, i] for i in conn]) + x_el = X_el + u_el + for ip in get_integration_points(element, Val{3}) + dN = get_dbasis(element, ip) + N = element(ip, time) + t = sum([kron(dN[:,i], x_el[i]') for i=1:length(x_el)]) + normals[:, conn] += ip.weight*Q*t'*N + end + end + # --> slave side normals in deformed state + n1 = Field(Vector[normals[:,i]/norm(normals[:,i]) for i in slave_element_nodes]) + + Wco = 0.0 + Wla = 0.0 + + for master_element in slave_element["master elements"] + X2 = master_element("geometry", time) + master_element_nodes = get_connectivity(master_element) + u2 = Field(Vector[u[:,i] for i in master_element_nodes]) + x2 = X2 + u2 + + # calculate segmentation: we care only about endpoints + # note: these are quadratic/cubic functions, analytical solution possible + xi1a = project_from_master_to_slave(slave_element, x1, n1, x2[1]) + xi1b = project_from_master_to_slave(slave_element, x1, n1, x2[end]) + xi1 = clamp([xi1a; xi1b], -1.0, 1.0) + l = 1/2*abs(xi1[2]-xi1[1]) + isapprox(l, 0.0) && continue # no contribution + + nnodes = size(slave_element, 2) + De = zeros(nnodes, nnodes) + Me = zeros(nnodes, nnodes) + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = get_basis(slave_element, xi_s) + De += w*diagm(vec(N1)) + Me += w*N1'*N1 + end + Ae = De*inv(Me) + + for ip in get_integration_points(slave_element, Val{5}) + # jacobian of slave element in deformed state + dN = get_dbasis(slave_element, ip) + j = sum([kron(dN[:,i], x1[i]') for i=1:length(x1)]) + w = ip.weight*norm(j)*l + xi_s = dot([1/2*(1-ip.xi); 1/2*(1+ip.xi)], xi1) + N1 = vec(get_basis(slave_element, xi_s)) + + # project gauss point to master element to evaluate shape function there + x_s = N1*x1 # coordinate in gauss point + n_s = N1*n1 # normal direction in gauss point + t_s = Q'*n_s + xi_m = project_from_slave_to_master(master_element, x_s, n_s, x2) + N2 = vec(get_basis(master_element, xi_m)) + x_m = N2*x2 + Phi = Ae*N1 + + gn = -dot(n_s, x_s - x_m) + gt = dot(t_s, x_s - x_m) + lan = dot(n_s, Phi*la1) + lat = dot(t_s, Phi*la1) + u_s = N1*u1 + u_m = N2*u2 + gu = dot(n_s, u_s - u_m) + + Wco += w*dot(Phi*la1, N1*u1 - N2*u2) + #Wla += w*(lan*gn + lat*gt) + #gn = min(0, gn) + Wla += 1/2*w*1e6*gn*gn + #info("gn = $(ForwardDiff.get_value(gn))") + #Wla += w*dot(dot(n_s, Phi*la1), dot(n_s, N1*u1 - N2*u2)) + end + + end + return Wco, Wla + end + + + function calculate_contact_rhs(x::Vector) + ndofs = round(Int, length(x)/2) + nnodes = round(Int, ndofs/field_dim) + u = reshape(x[1:ndofs], field_dim, nnodes) + la = reshape(x[ndofs+1:end], field_dim, nnodes) + fc, C = calculate_interface(u, la) + info("interface vector calculated.") + return vec(full([fc; C])) + end + + # x doesn't mean deformed configuration here + x = [problem.assembly.u; problem.assembly.la] + ndofs = round(Int, length(x)/2) + if ndofs == 0 + info("INITIALIZING THINGS") + problem.assembly.u = zeros(16) + problem.assembly.la = zeros(16) + x = [problem.assembly.u; problem.assembly.la] + ndofs = round(Int, length(x)/2) + end + + function add_fco!() + get_PI(x::Vector) = calculate_interface_PE(x)[1] + A, allresults = ForwardDiff.hessian(get_PI, x, ForwardDiff.AllResults) + b = -ForwardDiff.gradient(allresults) + info("PE = $(ForwardDiff.value(allresults))") + A = sparse(A) + b = sparse(b) + SparseMatrix.droptol!(A, 1.0e-12) + SparseMatrix.droptol!(b, 1.0e-12) + K = A[1:ndofs,1:ndofs] + C1 = transpose(A[1:ndofs,ndofs+1:end]) + C2 = A[ndofs+1:end,1:ndofs] + D = A[ndofs+1:end,ndofs+1:end] + f = b[1:ndofs] + g = b[ndofs+1:end] + add!(assembly.K, K) + add!(assembly.C1, C1) + add!(assembly.C2, C2) + add!(assembly.D, D) + add!(assembly.f, f) + add!(assembly.g, g) + end + #add_fco!() + + function add_wla!() + get_PI(x::Vector) = calculate_interface_PE(x)[2] + A, allresults = ForwardDiff.hessian(get_PI, x, ForwardDiff.AllResults) + b = -ForwardDiff.gradient(allresults) + info("PE = $(ForwardDiff.value(allresults))") + A = sparse(A) + b = sparse(b) + SparseMatrix.droptol!(A, 1.0e-12) + SparseMatrix.droptol!(b, 1.0e-12) + #info("A") + #println(full(A)) + K = A[1:ndofs,1:ndofs] + C1 = transpose(A[1:ndofs,ndofs+1:end]) + C2 = A[ndofs+1:end,1:ndofs] + D = A[ndofs+1:end,ndofs+1:end] + f = b[1:ndofs] + g = b[ndofs+1:end] + + add!(assembly.K, K) + add!(assembly.C1, C1) + add!(assembly.C2, C2) + add!(assembly.D, D) + add!(assembly.f, f) + add!(assembly.g, g) + end + add_wla!() + + return + +end + +mesh, body1, body2, bc_top, bc_bottom, contact = divided_block_problem() +bc_top.properties.formulation = :incremental +bc_bottom.properties.formulation = :incremental +contact.properties.formulation = :forwarddiff +contact.assembly.u = zeros(16) +contact.assembly.la = zeros(16) +assemble!(contact.assembly, contact, contact.elements[1], 0.0, Val{:forwarddiff}) + diff --git a/src/problems.jl b/src/problems.jl index 2cd5371..3097436 100644 --- a/src/problems.jl +++ b/src/problems.jl @@ -166,16 +166,22 @@ function update_assembly!(problem, u, la) # copy current solutions to previous ones and add/replace new solution assembly.u_prev = copy(assembly.u) assembly.la_prev = copy(assembly.la) - if get_formulation_type(problem) == :incremental - info("$(problem.name): incremental formulation, adding increment to solution vector") - #info("solution vector:") - #dump(round(u, 3)') - assembly.u += u - else + if get_formulation_type(problem) == :total info("$(problem.name): total formulation, replacing solution vector with new values") assembly.u = u + assembly.la = la + elseif get_formulation_type(problem) == :incremental + info("$(problem.name): incremental formulation, adding increment to solution vector") + assembly.u += u + assembly.la = la + elseif get_formulation_type(problem) == :forwarddiff + info("$(problem.name): forwarddiff formulation, adding increment to solution vector") + assembly.u += u + assembly.la += la + else + info("$(problem.name): unknown formulation type, don't know what to do with results") + error("serious failure with problem formulation: $(get_formulation_type(problem))") end - assembly.la = la # calculate change of norm assembly.u_norm_change = norm(assembly.u - assembly.u_prev) diff --git a/src/solvers.jl b/src/solvers.jl index 22aa4af..31a172a 100644 --- a/src/solvers.jl +++ b/src/solvers.jl @@ -141,9 +141,11 @@ type Solver name :: ASCIIString # some descriptive name for problem time :: Real # current time iteration :: Int # iteration counter + norms :: Vector{Tuple} # solution norms for convergence studies ndofs :: Int # total dimension of global stiffness matrix, i.e., dim*nnodes problems :: Vector{Problem} is_linear_system :: Bool # setting this to true makes assumption of one step convergence + nonlinear_system_min_iterations :: Int64 nonlinear_system_max_iterations :: Int64 nonlinear_system_convergence_tolerance :: Float64 nonlinear_system_error_if_no_convergence :: Bool @@ -155,9 +157,11 @@ function Solver(name::ASCIIString="default solver", time::Real=0.0) name, time, 0, # iteration # + [], # solution norms in (norm(u), norm(la)) tuples 0, # ndofs [], # array of problems false, # is_linear_system + 1, # min nonlinear iterations 10, # max nonlinear iterations 5.0e-5, # nonlinear iteration convergence tolerance true, # throw error if no convergence @@ -277,12 +281,14 @@ crosspoints. function get_boundary_assembly(solver::Solver) ndofs = solver.ndofs @assert ndofs != 0 + Kc = spzeros(ndofs, ndofs) C1 = spzeros(ndofs, ndofs) C2 = spzeros(ndofs, ndofs) D = spzeros(ndofs, ndofs) g = spzeros(ndofs, 1) for problem in get_boundary_problems(solver) assembly = problem.assembly + Kc_ = sparse(assembly.K, ndofs, ndofs) C1_ = sparse(assembly.C1, ndofs, ndofs) C2_ = sparse(assembly.C2, ndofs, ndofs) D_ = sparse(assembly.D, ndofs, ndofs) @@ -297,12 +303,13 @@ function get_boundary_assembly(solver::Solver) handle_overconstraint_error!(problem, overconstrained_nodes, overconstrained_dofs, C1, C1_, C2, C2_, D, D_, g, g_) end + Kc += Kc_ C1 += C1_ C2 += C2_ D += D_ g += g_ end - return C1, C2, D, g + return Kc, C1, C2, D, g end @@ -316,10 +323,10 @@ function solve_linear_system(solver::Solver, ::Type{Val{:DirectLinearSolver}}) K, f = get_field_assembly(solver) # assemble boundary problems - C1, C2, D, g = get_boundary_assembly(solver) + Kc, C1, C2, D, g = get_boundary_assembly(solver) # construct global system Ax=b and solve using lu factorization - A = [K C1'; C2 D] + A = [K+Kc C1'; C2 D] b = [f; g] nz = get_nonzero_rows(A) @@ -379,6 +386,7 @@ end """ Main solver loop. """ function call(solver::Solver) + # 1. initialize each problem so that we can start nonlinear iterations for problem in solver.problems initialize!(problem, solver.time) @@ -394,6 +402,7 @@ function call(solver::Solver) # 2.2 call solver for linearized system (default: direct lu factorization) u, la = solve_linear_system(solver, Val{solver.linear_system_solver}) + push!(solver.norms, (norm(u), norm(la))) # 2.3 update solution back to elements for problem in solver.problems @@ -404,7 +413,11 @@ function call(solver::Solver) # 2.4 check convergence if has_converged(solver) info("Converged in $(solver.iteration) iterations.") - return true + if solver.iteration < solver.nonlinear_system_min_iterations + info("Converged but continuing") + else + return true + end end end diff --git a/src/sparse.jl b/src/sparse.jl index ac9527f..37250d3 100644 --- a/src/sparse.jl +++ b/src/sparse.jl @@ -4,18 +4,22 @@ # Sparse utils to make assembly of local and global matrices easier. # Unoptimized but should do all necessary stuff for at start. -type SparseMatrixCOO +type SparseMatrixCOO{T<:Real} I :: Vector{Int} J :: Vector{Int} - V :: Vector{Float64} + V :: Vector{T} end typealias SparseMatrixIJV SparseMatrixCOO function SparseMatrixCOO() - SparseMatrixCOO([], [], []) + SparseMatrixCOO{Float64}([], [], []) end +#function SparseMatrixCOO{T}() +# SparseMatrixCOO{T}([], [], []) +#end + function Base.convert(::Type{SparseMatrixCOO}, A::SparseMatrixCSC) return SparseMatrixCOO(findnz(A)...) end @@ -80,7 +84,7 @@ function Base.(:+)(A::SparseMatrixIJV, B::SparseMatrixIJV) return C end -function Base.full(A::SparseMatrixIJV, args...) +function Base.full(A::SparseMatrixCOO, args...) return full(sparse(A.I, A.J, A.V, args...)) end @@ -94,7 +98,7 @@ Example >>> S = [3, 4] >>> M = [6, 7, 8] >>> data = Float64[5 6 7; 8 9 10] ->>> A = SparseMatrixIJV() +>>> A = SparseMatrixCOO() >>> add!(A, S, M, data) >>> full(A) 4x8 Array{Float64,2}: @@ -104,7 +108,7 @@ Example 0.0 0.0 0.0 0.0 0.0 8.0 9.0 10.0 """ -function add!(A::SparseMatrixIJV, dofs1::Vector{Int}, dofs2::Vector{Int}, data::Matrix{Float64}) +function add!(A::SparseMatrixCOO, dofs1::Vector{Int}, dofs2::Vector{Int}, data::Matrix) n, m = size(data) for j=1:m for i=1:n @@ -112,11 +116,16 @@ function add!(A::SparseMatrixIJV, dofs1::Vector{Int}, dofs2::Vector{Int}, data:: push!(A.J, dofs2[j]) end end -# append!(A.I, repeat(dofs1, outer=[m])) -# append!(A.J, repeat(dofs2, inner=[n])) append!(A.V, vec(data)) end +""" Add sparse matrix of CSC to COO. """ +function add!(A::SparseMatrixCOO, B::SparseMatrixCSC) + I, J, V = findnz(B) + C = SparseMatrixCOO(I, J, V) + append!(A, C) +end + """ Add new data to COO Sparse vector. """ function add!(A::SparseMatrixCOO, dofs::Vector{Int}, data::Array{Float64}, dim::Int=1) if length(dofs) != length(data) diff --git a/src/xdmf.jl b/src/xdmf.jl index b6db5f2..578b9c9 100644 --- a/src/xdmf.jl +++ b/src/xdmf.jl @@ -73,11 +73,11 @@ function xdmf_new_grid(temporal_collection; time=0) return grid end -function xdmf_new_mesh!(grid, nodes, elements) +function xdmf_new_mesh!(grid, nodes, elements; datatype="XYZ") # 1. write nodes geometry = new_child(grid, "Geometry") - set_attribute(geometry, "Type", "XYZ") + set_attribute(geometry, "Type", datatype) dataitem = new_child(geometry, "DataItem") set_attribute(dataitem, "DataType", "Float") ndim = sum([length(node) for node in nodes])