postprocessing utility

This commit is contained in:
Jukka Aho
2016-07-14 12:43:41 +03:00
parent 8f92a41b8a
commit 1bd1ec9fa9
21 changed files with 499 additions and 276 deletions
+57 -29
View File
@@ -8,36 +8,64 @@ using JuliaFEM.Abaqus
using JuliaFEM.Testing
# to turn on automatic file download, set
# ENV["ABAQUS_DOWNLOAD_URL"] = http://<domain>:2080/v2016/books/eif
# if don't want to download all stuff to current directory,
# set also e.g. ENV["ABAQUS_DOWNLOAD_DIR"] = "/tmp"
# ENV["ABAQUS_DOWNLOAD_URL"] = "http://<domain>:2080/v2016/books/eif"
# if don't want to download all stuff to current directory, set also
# ENV["ABAQUS_DOWNLOAD_DIR"] = "/tmp"
#=
test_name = "ecs4sfs1"
@testset "$test_name" begin
abaqus_run_test(test_name) || return
results = abaqus_read_results(test_name)
""" Run test, return true if simulation is succesfull, i.e. no errors raise
during parsing .inp file or execution of model. This doesn't mean that results
are meaningful; they must be checked in separately. Running model only verifies
that no catastrophic failures happen during file parsing. """
function abaqus_run_test(name)
return_code = abaqus_run_model(name; fetch=true, verbose=true)
return_code == 0 && return true
return false
end
=#
@testset "ec38sfs2" begin
return_code = abaqus_run_model("ec38sfs2"; fetch=true, verbose=true)
return_code == 0 || return
@test return_code == 0
#=
xdmf = abaqus_open_results("ec38sfs2")
side, opts = read_result(xdmf, "SECTION/side")
@test isapprox(side["SOFM"], 3464.0)
@test isapprox(side["SOF1"], 2000.0)
@test isapprox(side["SOF2"], 2000.0)
@test isapprox(side["SOF3"], 2000.0)
@test isapprox(side["SOMM"], 2828.0)
@test isapprox(side["SOM1"], 0.0)
@test isapprox(side["SOM2"], 2000.0)
@test isapprox(side["SOM3"], -2000.0)
@test isapprox(side["SOAREA"], 2.000)
@test isapprox(side["SOCF1"], 2/3)
@test isapprox(side["SOCF2"], 2/3)
@test isapprox(side["SOCF3"], 1/6)
=#
@testset "JuliaFEM-ABAQUS interface" begin
@testset "1 Element Verification" begin
@testset "1.2 Eigenvalue tests" begin
@testset "1.2.1 Eigenvalue extraction for single unconstrained elements" begin
@testset "Acoustic elements" begin
@testset "AC1D2 elements." begin
# abaqus_run_test("ec12afe1") || return
end
end
@testset "Three-dimensional continuum elements" begin
@testset "C3D10 elements." begin
# abaqus_run_test("ec3asfe1") || return
end
end
end
end
@testset "1.3 Simple load tests" begin
@testset "1.3.1 Membrane loading of plane stress, plane strain, membrane, and shell elements" begin
@testset "CPS4 elements." begin
# abaqus_run_test("ecs4sfs1") || return
end
end
@testset "1.3.3 Three-dimensional solid elements" begin
@testset "C3D8 elements." begin
abaqus_run_test("ec38sfs2") || return
#= to check also results:
xdmf = abaqus_open_results("ec38sfs2")
side, opts = read_result(xdmf, "SECTION/side")
@test isapprox(side["SOFM"], 3464.0)
@test isapprox(side["SOF1"], 2000.0)
@test isapprox(side["SOF2"], 2000.0)
@test isapprox(side["SOF3"], 2000.0)
@test isapprox(side["SOMM"], 2828.0)
@test isapprox(side["SOM1"], 0.0)
@test isapprox(side["SOM2"], 2000.0)
@test isapprox(side["SOM3"], -2000.0)
@test isapprox(side["SOAREA"], 2.000)
@test isapprox(side["SOCF1"], 2/3)
@test isapprox(side["SOCF2"], 2/3)
@test isapprox(side["SOCF3"], 1/6)
=#
end
end
end
end
end
+2 -2
View File
@@ -122,7 +122,7 @@ end
slaves = get_slave_elements(contact)
node_ids, la = get_nodal_vector(slaves, "reaction force", 0.0)
node_ids, n = get_nodal_vector(slaves, "normal", 0.0)
pres = [dot(ni, lai) for (ni, lai) in zip(n, la)]
pres = [dot(ni, -lai) for (ni, lai) in zip(n, la)]
#@test isapprox(maximum(pres), 4060.010799583303)
# 12 % error in maximum pressure
@test isapprox(maximum(pres), 3585.0; rtol = 12.0e-2)
@@ -137,7 +137,7 @@ end
n = sel("normal", ip, time)
t = Q'*n
la = sel("reaction force", ip, time)
Rn += w*dot(n, la)
Rn += w*dot(n, -la)
Rt += w*dot(t, la)
end
end
+26
View File
@@ -0,0 +1,26 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
using JuliaFEM.Testing
@testset "1d strain" begin
X = Dict{Int64, Vector{Float64}}(
1 => [0.0, 0.0, 0.0],
2 => [1.0, 1.0, 1.0])
u = Dict{Int64, Vector{Float64}}(
1 => [0.0, 0.0, 0.0],
2 => [1.0, 1.0, 1.0])
element = Element(Seg2, [1, 2])
update!(element, "geometry", X)
detJ = element([0.0], 0.0, Val{:detJ})
info("detJ = $detJ")
@test isapprox(detJ, sqrt(3)/2)
J = element([0.0], 0.0, Val{:Jacobian})
info("J = $J")
@test isapprox(J, [0.5 0.5 0.5])
update!(element, "displacement", u)
# FIXME
# gradu = element("displacement", [0.0], 0.0, Val{:Grad})
# info("1d bar: ∇u = $gradu")
end
@@ -7,9 +7,15 @@ using JuliaFEM.Postprocess
using JuliaFEM.Testing
#=
- solve 2d plane stress problem with known solution
- test postprocessing of nodal fields: (geometry, displacement
reaction force, concentrated force)
- solve 2d plane stress problem with known solution:
surface traction force in 2d
volume load in 2d
reaction force
- test postprocessing of nodal fields:
geometry
displacement
reaction force
concentrated force
=#
@testset "test 2d linear elasticity with surface + volume load" begin
meshfile = "/geometry/2d_block/BLOCK_1elem.med"
@@ -42,8 +48,13 @@ using JuliaFEM.Testing
update!(bc_sym_13, "displacement 2", 0.0)
solver = LinearSolver(block, traction, bc_sym_23, bc_sym_13)
# assemble!(solver)
# dump(full(bc_sym_23.assembly.C1))
solver()
info("u = ", block.assembly.u)
info("λ = ", block.assembly.la)
f = 288.0
g = 576.0
E = 288.0
@@ -51,40 +62,41 @@ using JuliaFEM.Testing
u3_expected = f/E*[-nu, 1] + g/(2*E)*[-nu, 1]
# fetch nodal results X + u and join them into one table using DataFrames
X = block(DataFrame, "geometry", :COOR, 0.0)
u = block(DataFrame, "displacement", :U, 0.0)
results = join(X, u, on=:id, kind=:outer)
X = solver(DataFrame, "geometry", :COOR)
u = solver(DataFrame, "displacement", :U)
la = solver(DataFrame, "reaction force", :RF)
f = solver(DataFrame, "concentrated force", :CF)
results = join(X, u, on=:NODE, kind=:outer)
results = join(results, la, on=:NODE, kind=:outer)
length(f) != 0 && (results = join(results, f, on=:NODE, kind=:outer))
sort!(results, cols=[:NODE])
println(results)
u3 = results[:N3, [:U1, :U2]]
u3 = extract(results, NODE=:N3, :U1, :U2)
@test isapprox(u3, u3_expected)
#=
info("strain")
for ip in get_integration_points(block.elements[1])
eps = ip("strain")
@printf "%i | %8.3f %8.3f | %8.3f %8.3f %8.3f\n" ip.id ip.coords[1] ip.coords[2] eps[1] eps[2] eps[3]
# TODO: to postprocess ...?
#@test isapprox(eps, [u3[1], u3[2], 0.0])
end
# element details
el = first(block.elements)
S1 = block(el, [0.0, 0.0], 0.0, Val{:S})
S1 = S1[[1,4,2]]
E1= block(el, [0.0, 0.0], 0.0, Val{:E})
E1 = E1[[1,4,2]]
C1 = block(el, [0.0, 0.0], 0.0, Val{:COORD})
info("strain = $E1, stress = $S1, at $C1")
@test isapprox(E1, [-2/3, 2.0, 0.0])
@test isapprox(S1, [0.0, 576.0, 0.0])
@test isapprox(C1, [0.5, 0.5])
info("stress")
for ip in get_integration_points(block.elements[1])
sig = ip("stress")
@printf "%i | %8.3f %8.3f | %8.3f %8.3f %8.3f\n" ip.id ip.coords[1] ip.coords[2] sig[1] sig[2] sig[3]
# TODO: to postprocess
#@test isapprox(sig, [0.0, g, 0.0])
end
S1 = block(DataFrame, 0.0, Val{:S})
E1 = block(DataFrame, 0.0, Val{:E})
C1 = block(DataFrame, 0.0, Val{:COORD})
calc_nodal_values!(block.elements, "strain", 3, 0.0)
calc_nodal_values!(block.elements, "stress", 3, 0.0)
info(block.elements[1]["stress"](0.0))
node_ids, strain = get_nodal_vector(block.elements, "strain", 0.0)
node_ids, stress = get_nodal_vector(block.elements, "stress", 0.0)
# TODO: to postprocess
#@test isapprox(stress[1], [0.0, g, 0.0])
#@test isapprox(strain[1], [u3[1], u3[2], 0.0])
=#
println(S1)
println(E1)
println(C1)
S = solver(DataFrame, 0.0, Val{:S})
println(S)
end
+2
View File
@@ -106,6 +106,7 @@ end
@test isapprox(fb, 1.0)
end
#= unnecessary feature
@testset "add two time dependent fields to element at once" begin
el = Element(Seg2, [1, 2])
update!(el, "foo1", 1.0 => 1.0)
@@ -113,6 +114,7 @@ end
update!(el, "foo2", 1.0 => 1.0, 2.0 => 2.0)
@test isapprox(el("foo1", 1.5), el("foo2", 1.5))
end
=#
@testset "add elements to elements" begin
el1 = Element(Seg2, [1, 2])
+2 -1
View File
@@ -58,7 +58,8 @@ end
el2 = Element(Seg2, [1, 2])
update!(el2, "geometry", X)
# linear ramp from 0 -> 6 in time 0 -> 1
update!(el2, "temperature flux", 0.0 => 0.0, 1.0 => 6.0)
update!(el2, "temperature flux", 0.0 => 0.0)
update!(el2, "temperature flux", 1.0 => 6.0)
# define heat problem and push elements to problem
problem = Problem(Heat, "one element heat problem", 1)
+25 -33
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Testing
@testset "test eigenvalues for single tet4 element" begin
function get_model()
X = Dict{Int, Vector{Float64}}(
1 => [2.0, 3.0, 4.0],
2 => [6.0, 3.0, 2.0],
@@ -19,33 +19,38 @@ using JuliaFEM.Testing
e2 = Element(Tri3, [1, 2, 3])
update!([e1, e2], "geometry", X)
update!([e1, e2], "displacement", 0.0 => u)
update!(e1, "youngs modulus" => 96.0,
"poissons ratio" => 1.0/3.0,
"density" => 420.0)
update!(e2, "displacement 1" => 0.0,
"displacement 2" => 0.0,
"displacement 3" => 0.0)
update!(e1, "youngs modulus" => 96.0)
update!(e1, "poissons ratio" => 1.0/3.0)
update!(e1, "density" => 420.0)
update!(e2, "displacement 1" => 0.0)
update!(e2, "displacement 2" => 0.0)
update!(e2, "displacement 3" => 0.0)
p1 = Problem(Elasticity, 3)
p1.properties.finite_strain = false
p1.properties.geometric_stiffness = false
p2 = Problem(Dirichlet, p1)
push!(p1, e1)
push!(p2, e2)
s1 = Solver(Modal)
s1.properties.which = :LM
push!(s1, p1, p2)
solver = Solver(Modal)
solver.properties.which = :LM
push!(solver, p1, p2)
return solver
end
s1(; debug=true)
@test isapprox(s1.properties.eigvals, [4/3, 1/3])
@testset "test eigenvalues for single tet4 element" begin
solver = get_model()
solver(; debug=true)
@test isapprox(solver.properties.eigvals, [4/3, 1/3])
end
empty!(p1)
empty!(p2)
empty!(p1.assembly.M)
# p1.properties.finite_strain = true
p1.properties.geometric_stiffness = true
s1.properties.geometric_stiffness = true
s1(; debug=true)
@test isapprox(s1.properties.eigvals, [5/3, 2/3])
@testset "test eigenvalues for single tet4 element, with geometric stiffness" begin
solver = get_model()
problem = first(solver.problems)
# problem.properties.finite_strain = true
problem.properties.geometric_stiffness = true
solver.properties.geometric_stiffness = true
solver(; debug=true)
@test isapprox(solver.properties.eigvals, [5/3, 2/3])
end
@testset "test poisson problem modal analysis without tie" begin
@@ -58,10 +63,6 @@ end
6 => [1.0, 3.0],
7 => [1.0, 9.0],
8 => [0.0, 9.0])
T = Dict{Int64, Float64}()
for i=1:8
T[i] = 0.0
end
el1 = Element(Quad4, [1, 2, 3, 4])
el2 = Element(Quad4, [4, 3, 7, 8])
el3 = Element(Seg2, [1, 2])
@@ -69,15 +70,12 @@ end
update!([el1, el2, el3, el4], "geometry", X)
update!([el1, el2], "density", 6.0)
update!([el1, el2], "temperature thermal conductivity", 36.0)
#update!([el1, el2], "temperature", 0.0 => T)
update!([el1, el2], "temperature", T)
update!([el3, el4], "temperature 1", 0.0)
p1 = Problem(Heat, "combined body", 1)
p1.properties.formulation = "2D"
p2 = Problem(Dirichlet, "fixed ends", 1, "temperature")
push!(p1, el1, el2)
push!(p2, el3, el4)
solver = Solver(Modal)
push!(solver, p1, p2)
solver()
@@ -94,10 +92,6 @@ end
6 => [1.0, 3.0],
7 => [1.0, 9.0],
8 => [0.0, 9.0])
T = Dict{Int64, Float64}()
for i=1:8
T[i] = 0.0
end
el1 = Element(Quad4, [1, 2, 3, 4])
el2 = Element(Quad4, [5, 6, 7, 8])
el3 = Element(Seg2, [1, 2])
@@ -105,8 +99,6 @@ end
el5 = Element(Seg2, [3, 4])
el6 = Element(Seg2, [5, 6])
update!([el1, el2, el3, el4, el5, el6], "geometry", X)
#update!([el1, el2], "temperature", 0.0 => T)
update!([el1, el2], "temperature", T)
update!([el1, el2], "density", 6.0)
update!([el1, el2], "temperature thermal conductivity", 36.0)
update!([el3, el4], "temperature 1", 0.0)
+2 -1
View File
@@ -81,5 +81,6 @@ end
la = slave("reaction force", [0.0], 0.0)
info("u = $u, la = $la")
@test isapprox(u, [-0.2, -0.15])
@test isapprox(la, [0.0, 30.375])
@test isapprox(la, [0.0, -30.375])
# FIXME
end
+2 -1
View File
@@ -187,8 +187,9 @@ end
slave_elements = get_slave_elements(interface)
node_ids, la = get_nodal_vector(slave_elements, "reaction force", 0.0)
for lai in la
@test isapprox(lai, [0.0, 10.0])
@test isapprox(lai, [0.0, -10.0])
end
# FIXME
end
function JuliaFEM.get_mesh(::Type{Val{Symbol("curved 2d block splitted to upper and lower")}})
-52
View File
@@ -72,58 +72,6 @@ testdata = """\
</Xdmf>
"""
function test_write_to_xml()
nodes = Vector{Float64}[
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
[0.5, 0.0, 0.0],
[0.5, 0.5, 0.0],
[0.0, 0.5, 0.0],
[0.0, 0.0, 0.5],
[0.5, 0.0, 0.5],
[0.0, 0.5, 0.5],
[1.0, 1.0, 1.0],
[2.0, 1.0, 1.0],
[1.0, 2.0, 1.0],
[1.0, 1.0, 2.0],
[1.5, 1.0, 1.0],
[1.5, 1.5, 1.0],
[1.0, 1.5, 1.0],
[1.0, 1.0, 1.5],
[1.5, 1.0, 1.5],
[1.0, 1.5, 1.5]]
elements = [
(:Tet10, [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
(:Tet10, [11, 12, 13, 14, 15, 16, 17, 18, 19, 20])]
displacement_field = nodes # same structure
xdoc, model = JuliaFEM.Postprocess.xdmf_new_model()
temporal_collection = JuliaFEM.Postprocess.xdmf_new_temporal_collection(model)
grid = JuliaFEM.Postprocess.xdmf_new_grid(temporal_collection; time=1)
JuliaFEM.Postprocess.xdmf_new_mesh!(grid, nodes, elements)
JuliaFEM.Postprocess.xdmf_new_nodal_field!(grid, "Displacement", displacement_field)
JuliaFEM.Postprocess.xdmf_save_model(xdoc, "/tmp/foo.xmf")
#info("exported data model: \n$(string(xdoc))")
#@test string(xdoc) == testdata
d1 = split(string(xdoc), "\n")
# d2 = split(testdata, "\n")
d2 = open(readlines, Pkg.dir("JuliaFEM")*"/test/testdata/quad_two_tet10.xmf")
println("comparing string")
for i in 1:length(d1)
println("d1: $(d1[i])")
println("d2: $(d2[i])")
#status = d1 == d2 ? "MATCHES" : "NO MATCH"
#info("line: $(d1[i]) $status")
#if d1 != d2
# info("should be:\n$(d2[i])")
#end
d1 == d2 || error("No match")
end
end
@testset "write simple xmf file" begin
X = Dict{Int64, Vector{Float64}}(
1 => [0.0, 0.0],
+15 -1
View File
@@ -4,7 +4,7 @@
using JuliaFEM
using JuliaFEM.Testing
@testset "test initialize field problem" begin
@testset "test initialize scalar field problem" begin
el = Element(Seg2, [1, 2])
pr = Problem(Heat, 1)
push!(pr, el)
@@ -19,6 +19,20 @@ using JuliaFEM.Testing
@test length(last(el, "temperature").data) == 2
end
@testset "test initialize vector field problem" begin
el = Element(Seg2, [1, 2])
pr = Problem(Elasticity, 2)
push!(pr, el)
initialize!(pr)
@test haskey(el, "displacement")
@test length(el["displacement"]) == 1
# this way we access to field at default time t=0.0, it's different than ^!
@test length(el("displacement")) == 2
# length of single increment
@test length(el("displacement", 0.0)) == 2
@test length(last(el, "displacement").data) == 2
end
@testset "test initialize boundary problem" begin
el = Element(Seg2, [1, 2])
pr = Problem(Dirichlet, "bc", 1, "temperature")