lot of new tests, echangement of modal solver, eigenvalue analysis with mesh tie

This commit is contained in:
Jukka Aho
2016-07-27 18:12:24 +03:00
parent fbcc1912d8
commit 67ace8acdc
21 changed files with 717 additions and 35 deletions
+51
View File
@@ -0,0 +1,51 @@
# 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.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Testing
#=
Two rings, RING1 = inner, RING2 = outer, RINGS combined mesh. Set T=1.0 for
inner ring and T=2.0 for outer ring, measure temperature from middle of ring.
Results are calculated using Code Aster for comparison.
=#
@testset "test 3d heat, two rings, and compare to CA solution" begin
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(meshfile, "RINGS_UNION")
rings = Problem(Heat, "RINGS", 1)
# rings.elements = create_elements(mesh; element_type=:Tet4)
rings.elements = create_elements(mesh, "RING1", "RING2")
update!(rings.elements, "temperature thermal conductivity", 1.0)
bc_inner = Problem(Dirichlet, "INNER SURFACE", 1, "temperature")
bc_inner.elements = create_elements(mesh, "RING1_INNER")
bc_outer = Problem(Dirichlet, "OUTER SURFACE", 1, "temperature")
bc_outer.elements = create_elements(mesh, "RING2_OUTER")
update!(bc_inner, "temperature 1", 1.0)
update!(bc_outer, "temperature 1", 2.0)
info("# of elements in RING1_INNER = ", length(bc_inner.elements))
info("# of elements in RING2_OUTER = ", length(bc_outer.elements))
solver = LinearSolver(rings, bc_inner, bc_outer)
solver()
temp_jf = rings("temperature", 0.0)
fn = Pkg.dir("JuliaFEM") * "/test/testdata/rings.rmed"
results = RMEDFile(fn)
nodes = aster_read_nodes(results)
temp_ca = aster_read_data(results, "TEMP")
passed = true
for j in sort(collect(keys(temp_jf)))
X = nodes[j]
T1 = temp_jf[j]
T2 = temp_ca[j]
rtol = norm(T1-T2) / max(T1,T2)
@printf "% 5i : %8.5f %8.5f %8.5f | %8.5f %8.5f | %8.5e\n" j X... T1 T2 rtol
passed &= rtol < 1.0e-12
end
@test passed
end
+69 -6
View File
@@ -40,10 +40,29 @@ Fixed-fixed solution is ωᵢ = λᵢ²√(EI/ρA) , where λᵢ = cosh(λᵢℓ
2: 7.853204624095838
3: 10.995607838001671
Youngs modulus is tuned such that lowest eigenfrequency matches 1.0
5 lowest eigenfrequencies using Code Aster and Tet4 elements:
numéro fréquence (HZ) norme d'erreur
1 1.19789E+00 2.20137E-12
2 1.20179E+00 1.99034E-12
3 3.07391E+00 3.29226E-13
4 3.08812E+00 2.91550E-13
5 4.87370E+00 2.95986E-13
5 lowest eigenfrequencies using Code Aster and Tet10 elements:
numéro fréquence (HZ) norme d'erreur
1 9.65942E-01 1.54950E-11
2 9.66160E-01 1.62712E-11
3 2.52127E+00 2.06544E-12
4 2.52187E+00 1.77970E-12
5 3.48584E+00 9.96170E-13
[1] De Silva, Clarence W. Vibration: fundamentals and practice. CRC press, 2006, p.355
=#
@testset "long rod under point load" begin
@testset "long rod natural frequencies" begin
mesh_file = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(mesh_file, "CYLINDER_20_TET10")
# for (id, coords) in mesh.nodes
@@ -51,7 +70,8 @@ Fixed-fixed solution is ωᵢ = λᵢ²√(EI/ρA) , where λᵢ = cosh(λᵢℓ
# end
body = Problem(Elasticity, "rod", 3)
body.elements = create_elements(mesh, "CYLINDER")
E = 50475.44814745859
#E = 50475.44814745859
E = 50475.5
rho = 1.0
update!(body.elements, "youngs modulus", E)
update!(body.elements, "poissons ratio", 0.3)
@@ -121,13 +141,27 @@ Fixed-fixed solution is ωᵢ = λᵢ²√(EI/ρA) , where λᵢ = cosh(λᵢℓ
info("freq_a = $freq_a")
solver = Solver(Modal, body, fixed1, fixed2)
solver.properties.nev = 5
solver()
freqs = keys(body["displacement"])
freqs_jf = sqrt(solver.properties.eigvals)/(2.0*pi)
# with Tet4 elements
#freqs_ca = [1.19789E+00, 1.20179E+00, 3.07391E+00, 3.08813E+00, 4.87370E+00]
# with Tet10 elements
freqs_ca = [9.65942E-01, 9.66160E-01, 2.52127E+00, 2.52187E+00, 3.48584E+00]
rtol1 = norm(freq_sa - freqs[2])/max(freq_sa, freqs[2])
rtol2 = norm(freq_a - freqs[2])/max(freq_a, freqs[2])
# looks that juliafem results are more close to 1.0, maybe different integration order
rtol1 = norm(freq_sa - freqs_jf[1])/max(freq_sa, freqs_jf[1])
rtol2 = norm(freq_a - freqs_jf[1])/max(freq_a, freqs_jf[1])
info("rtol 1 = $rtol1, rtol 2 = $rtol2")
@test rtol2 < 1.0e-2
passed = true
for (f1, f2) in zip(freqs_jf, freqs_ca)
rtol = norm(f1-f2) / max(f1,f2)
@printf "JF: %8.5e | CA: %8.5e | rtol: %8.5e\n" f1 f2 rtol
passed &= (rtol < 3.0e-2)
end
@test rtol2 < 3.0e-2
@test passed
#=
result = XDMF()
for (i, freq) in enumerate(freqs)
@@ -138,5 +172,34 @@ Fixed-fixed solution is ωᵢ = λᵢ²√(EI/ρA) , where λᵢ = cosh(λᵢℓ
end
xdmf_save!(result, "/tmp/rod_nf.xmf")
=#
end
@testset "eigenvalues of cube (tet4)" begin
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(meshfile, "CUBE_TET4")
cube = Problem(mesh, Elasticity, "CUBE", 3)
update!(cube.elements, "youngs modulus", 10000.0)
update!(cube.elements, "poissons ratio", 0.3)
update!(cube.elements, "density", 10.0)
sym23 = create_elements(mesh, "FACE231")
update!(sym23, "displacement 1", 0.0)
sym13 = create_elements(mesh, "FACE131")
update!(sym13, "displacement 2", 0.0)
sym12 = create_elements(mesh, "FACE121")
update!(sym12, "displacement 3", 0.0)
bcs = Problem(Dirichlet, "bcs", 3, "displacement")
bcs.elements = [sym23; sym13; sym12]
solver = Solver(Modal)
solver.properties.nev = 5
push!(solver, cube, bcs)
solver()
freqs_jf = sqrt(solver.properties.eigvals)/(2.0*pi)
freqs_ca = [3.73724E+00, 3.73724E+00, 4.93519E+00, 6.59406E+00, 7.65105E+00]
for (f1, f2) in zip(freqs_jf, freqs_ca)
rtol = norm(f1-f2) / max(f1,f2)
@printf "JF: %8.5e | CA: %8.5e | rtol: %8.5e\n" f1 f2 rtol
@test rtol < 1.0e-5
end
end
+68
View File
@@ -0,0 +1,68 @@
# 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.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Testing
@testset "eigenvalues of CYLINDER1" begin
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(meshfile, "CYLINDER_1_TET4")
cylinder = Problem(mesh, Elasticity, "CYLINDER", 3)
update!(cylinder.elements, "youngs modulus", 10000.0)
update!(cylinder.elements, "poissons ratio", 0.3)
update!(cylinder.elements, "density", 10.0)
bc1 = create_elements(mesh, "FACE_YZ1")
update!(bc1, "displacement 1", 0.0)
update!(bc1, "displacement 2", 0.0)
update!(bc1, "displacement 3", 0.0)
bcs = Problem(Dirichlet, "bcs", 3, "displacement")
bcs.elements = bc1
solver = Solver(Modal)
solver.properties.nev = 3
push!(solver, cylinder, bcs)
solver()
freqs_jf = sqrt(solver.properties.eigvals)/(2.0*pi)
freqs_ca = [4.84532E+00, 4.90698E+00, 8.33813E+00]
passed = []
for (f1, f2) in zip(freqs_jf, freqs_ca)
rtol = norm(f1-f2) / max(f1,f2)
@printf "JF: %8.5e | CA: %8.5e | rtol: %8.5e\n" f1 f2 rtol
push!(passed, rtol < 1.0e-5)
end
@test reduce(&, passed)
end
@testset "eigenvalues of CYLINDER20" begin
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(meshfile, "CYLINDER_20_TET4")
cylinder = Problem(mesh, Elasticity, "CYLINDER", 3)
#update!(cylinder.elements, "youngs modulus", 10.0e6)
update!(cylinder.elements, "youngs modulus", 50475.5)
update!(cylinder.elements, "poissons ratio", 0.3)
#update!(cylinder.elements, "density", 10.0)
update!(cylinder.elements, "density", 1.0)
bc1 = create_elements(mesh, "FACE1", "FACE2")
update!(bc1, "displacement 1", 0.0)
update!(bc1, "displacement 2", 0.0)
update!(bc1, "displacement 3", 0.0)
bcs = Problem(Dirichlet, "bcs", 3, "displacement")
bcs.elements = bc1
solver = Solver(Modal)
solver.properties.nev = 3
push!(solver, cylinder, bcs)
solver()
freqs_jf = sqrt(solver.properties.eigvals)/(2.0*pi)
#freqs_ca = [8.82848E-01, 8.85353E-01, 5.30286E+00] # only face1 fixed
#freqs_ca = [5.33185E+00, 5.34920E+00, 1.36820E+01] # face1 and face2 fixed
freqs_ca = [1.19789E+00, 1.20179E+00, 3.07391E+00]
passed = []
for (f1, f2) in zip(freqs_jf, freqs_ca)
rtol = norm(f1-f2) / max(f1,f2)
@printf "JF: %8.5e | CA: %8.5e | rtol: %8.5e\n" f1 f2 rtol
push!(passed, rtol < 1.0e-5)
end
@test reduce(&, passed)
end
+175
View File
@@ -0,0 +1,175 @@
# 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.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Testing
#=
test subjects:
- modal analysis, with mesh tie contact
Fixed-fixed solution is ω = λ²(EI/ρA) , where λ = cosh(λ)cos(λ)
1: 4.730040744862704
2: 7.853204624095838
3: 10.995607838001671
[1] De Silva, Clarence W. Vibration: fundamentals and practice. CRC press, 2006, p.355
Code Aster solution:
--------------------
numéro fréquence (HZ) norme d'erreur
1 1.12946E+00 5.81018E-12
2 1.13141E+00 6.33463E-12
3 2.93779E+00 6.53408E-13
4 2.94143E+00 5.43970E-13
5 4.51684E+00 5.43252E-13
=#
comm_CA = """
DEBUT(PAR_LOT="NON")
MAIL = LIRE_MAILLAGE(FORMAT="MED", NOM_MED="CYLINDER_20_SPLITTED")
MO = AFFE_MODELE(
MAILLAGE=MAIL,
AFFE=_F(TOUT="OUI",
PHENOMENE="MECANIQUE", MODELISATION="3D"))
MAT = DEFI_MATERIAU(
ELAS=_F(E=50475.45, NU=0.3, RHO=1.0))
CHMAT = AFFE_MATERIAU(
MAILLAGE=MAIL,
AFFE=_F(TOUT="OUI", MATER=MAT))
BC1 = AFFE_CHAR_MECA(
MODELE=MO,
DDL_IMPO=(
_F(GROUP_MA=("CYLINDER_20_1_FACE1"), DX=0, DY=0, DZ=0)))
BC2 = AFFE_CHAR_MECA(
MODELE=MO,
DDL_IMPO=(
_F(GROUP_MA=("CYLINDER_20_2_FACE2"), DX=0, DY=0, DZ=0)))
# ESCL = SLAVE
# MAIT = MASTER
BC3 = AFFE_CHAR_MECA(
MODELE=MO,
LIAISON_MAIL=_F(
GROUP_MA_ESCL="CYLINDER_20_1_FACE2",
GROUP_MA_MAIT="CYLINDER_20_2"))
# assemble material stiffness matrix
RIGEL = CALC_MATR_ELEM(
MODELE=MO,
OPTION="RIGI_MECA",
CHAM_MATER=CHMAT,
CHARGE=(BC1, BC2, BC3))
NUMEDDL = NUME_DDL(
MATR_RIGI=RIGEL)
RIGAS = ASSE_MATRICE(
MATR_ELEM=RIGEL,
NUME_DDL=NUMEDDL)
# assemble mass matrix
MASSEL = CALC_MATR_ELEM(
MODELE=MO,
OPTION="MASS_MECA",
CHAM_MATER=CHMAT,
CHARGE=(BC1, BC2, BC3))
MASSAS = ASSE_MATRICE(
MATR_ELEM=MASSEL,
NUME_DDL=NUMEDDL)
# modal analysis, without geometric stiffness
BRESU = CALC_MODES(
MATR_RIGI=RIGAS,
MATR_MASS=MASSAS,
OPTION="BANDE",
CALC_FREQ=_F(
FREQ=(0.0, 5.0)))
# modal analysis, with geometric stiffness
BRESU = NORM_MODE(
reuse=BRESU,
MODE=BRESU,
NORME="TRAN")
IMPR_RESU(
MODELE=MO,
FORMAT="RESULTAT",
RESU=_F(RESULTAT=BRESU))
IMPR_RESU(
FORMAT="MED",
UNITE=80,
RESU=_F(RESULTAT=BRESU))
FIN()
"""
@testset "splitted rod with tie contact" begin
# CYLINDER_20_1_FACE1 -- CYLINDER_20_1_FACE2 -- CYLINDER_20_2_FACE_1 -- CYLINDER_20_2_FACE_2
mesh_file = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(mesh_file, "CYLINDER_20_SPLITTED")
body1 = Problem(mesh, Elasticity, "CYLINDER_20_1", 3)
body2 = Problem(mesh, Elasticity, "CYLINDER_20_2", 3)
for body in [body1, body2]
update!(body.elements, "youngs modulus", 54475.45)
update!(body.elements, "poissons ratio", 0.3)
update!(body.elements, "density", 1.0)
end
bc1 = Problem(mesh, Dirichlet, "CYLINDER_20_1_FACE1", 3, "displacement")
bc2 = Problem(mesh, Dirichlet, "CYLINDER_20_2_FACE2", 3, "displacement")
for bc in [bc1, bc2]
update!(bc.elements, "displacement 1", 0.0)
update!(bc.elements, "displacement 2", 0.0)
update!(bc.elements, "displacement 3", 0.0)
end
interface = Problem(Mortar, "interface between bodies", 3, "displacement")
slave = create_elements(mesh, "CYLINDER_20_1_FACE2")
master = create_elements(mesh, "CYLINDER_20_2_FACE1")
update!(slave, "master elements", master)
interface.elements = [slave; master]
solver = Solver(Modal, body1, body2, bc1, bc2, interface)
solver.properties.nev = 5
solver.properties.which = :SM
solver()
freqs_jf = sqrt(solver.properties.eigvals)/(2*pi)
freqs_ca = [1.12946E+00, 1.13141E+00, 2.93779E+00, 2.94143E+00, 4.51684E+00]
freq_jf = freqs_jf[1]
freq_ca = freqs_ca[1]
rtol = norm(freq_jf - freq_ca)/max(freq_jf, freq_ca)
info("rtol = $rtol")
for (i, freq) in enumerate(freqs_jf)
@printf "mode %i | freq JuliaFEM %8.3f | freq Code Aster %8.3f\n" i freqs_jf[i] freqs_ca[i]
end
if rtol > 1.0e-3
outfile = tempname() * ".xmf"
info("Something went wrong, results are saved to $outfile")
result = XDMF()
elems = [body1.elements; body2.elements]
for (i, freq) in enumerate(freqs_jf)
xdmf_new_result!(result, elems, freq)
xdmf_save_field!(result, elems, freq, "displacement"; field_type="Vector")
end
xdmf_save!(result, outfile)
end
@test rtol < 0.05
end
+61
View File
@@ -0,0 +1,61 @@
# 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.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Testing
#=
Two rings, RING1 is inner, RING2 is outer. Inner diameter is from 0.8 .. 0.9 and
outer ring is 0.9 .. 1.0. Contact surface pair is RING1_OUTER <- RING2_INNER.
Put constant temperature 1.0 for inner surface of inner ring and 2.0 for outer
surface of outer ring. We should expect constant temperature in contact surface.
This is conforming mesh so result should match to the conforming situation.
=#
@testset "test that curved interface transfers constant field without error, two rings problem" begin
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/primitives.med"
mesh = aster_read_mesh(meshfile, "RINGS")
ring1 = Problem(Heat, "RING1", 1)
ring1.elements = create_elements(mesh, "RING1")
update!(ring1.elements, "temperature thermal conductivity", 1.0)
ring2 = Problem(Heat, "RING2", 1)
ring2.elements = create_elements(mesh, "RING2")
update!(ring2.elements, "temperature thermal conductivity", 1.0)
bc_inner = Problem(Dirichlet, "INNER SURFACE", 1, "temperature")
bc_inner.elements = create_elements(mesh, "RING1_INNER")
update!(bc_inner, "temperature 1", 1.0)
bc_outer = Problem(Dirichlet, "OUTER SURFACE", 1, "temperature")
bc_outer.elements = create_elements(mesh, "RING2_OUTER")
update!(bc_outer, "temperature 1", 2.0)
interface = Problem(Mortar, "interface between rings", 1, "temperature")
interface_slave = create_elements(mesh, "RING1_OUTER")
interface_master = create_elements(mesh, "RING2_INNER")
interface.elements = [interface_slave; interface_master]
update!(interface_slave, "master elements", interface_master)
solver = LinearSolver(ring1, ring2, bc_inner, bc_outer, interface)
solver()
fn = Pkg.dir("JuliaFEM") * "/test/testdata/rings.rmed"
results = RMEDFile(fn)
nodes = aster_read_nodes(results)
temp_ca = aster_read_data(results, "TEMP")
passed = true
for j in sort(collect(keys(nodes)))
X = nodes[j]
T1 = solver("temperature", X, 0.0)
T2 = temp_ca[j]
rtol = norm(T1-T2) / max(T1,T2)
@printf "% 5i : %8.5f %8.5f %8.5f | %8.5f %8.5f | %8.5f\n" j X... T1 T2 rtol
passed = passed && (rtol < 1.0e-12)
end
@test passed
end
+9
View File
@@ -147,3 +147,12 @@ end
# @test isapprox(calculate_volume("PYRAMID_PYRAMID13_1", :Pyramid13, ?))
end
@testset "get nodal field from aster file" begin
fn = Pkg.dir("JuliaFEM") * "/test/testdata/rings.rmed"
medfile = JuliaFEM.Preprocess.RMEDFile(fn)
temp = JuliaFEM.Preprocess.aster_read_data(medfile, "TEMP")
info("temp = $temp")
# more like functional testing, results are what they are,
# we're happy to just have some results
@test true
end
+62
View File
@@ -3,6 +3,7 @@
using JuliaFEM
using JuliaFEM.Testing
using JuliaFEM.Preprocess
@testset "test projection" begin
C = [
@@ -28,5 +29,66 @@ using JuliaFEM.Testing
h_expected = [1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
@test isapprox(full(P), P_expected)
@test isapprox(full(h), h_expected)
nz = [5, 6, 7, 8]
info("is P'P positive definite? ", isposdef(P[:,nz]'P[:,nz]))
@test isposdef(P[:,nz]'P[:,nz])
end
@testset "test creating projection matrix from invertible problem" begin
# simple 3 element poisson problem
k = [1.0 -1.0; -1.0 1.0]
K = zeros(4, 4)
K[1:2,1:2] += k
K[2:3,2:3] += k
K[3:4,3:4] += k
# first dof homogeneous bc, last dof u₄ = 1
C = zeros(4, 4)
C[1,1] = 1.0
C[4,4] = 1.0
g = zeros(4)
g[1] = 0.0
g[4] = 1.0
P, h = create_projection(sparse(C), g, Val{:invertible})
info("P = ")
dump(full(P))
P_expected = zeros(4, 4)
P_expected[2,2] = P_expected[3,3] = 1.0
@test isapprox(full(P), P_expected)
#h_expected = [0.5, 1.0]
#@test isapprox(h, h_expected)
end
@testset "projection between surfaces" begin
# FIXME: creating mortar projection takes very long time.
meshfile = Pkg.dir("JuliaFEM") * "/test/testdata/joint.med"
isfile(meshfile) || return
mesh = aster_read_mesh(meshfile, "JOINT")
# top
bc1 = Problem(Dirichlet, "fixed1", 3, "displacement")
bc1.elements = create_elements(mesh, "FIXED1")
update!(bc1.elements, "displacement 1", 0.0)
update!(bc1.elements, "displacement 2", 0.0)
update!(bc1.elements, "displacement 3", 0.0)
# bottom
bc2 = Problem(Dirichlet, "fixed2", 3, "displacement")
bc2.elements = create_elements(mesh, "FIXED2")
update!(bc2.elements, "displacement 1", 0.0)
update!(bc2.elements, "displacement 2", 0.0)
update!(bc2.elements, "displacement 3", 0.0)
# joint
contact = Problem(Mortar, "joint", 3, "displacement")
master_elements = create_elements(mesh, "BODY1_TO_BODY2")
slave_elements = create_elements(mesh, "BODY2_TO_BODY1")
update!(slave_elements, "master elements", master_elements)
contact.elements = [master_elements; slave_elements]
solver = Solver(Modal)
push!(solver, bc1, bc2, contact)
assemble!(solver)
Kb, C1, C2, D, fb, g = get_boundary_assembly(solver)
P, h = create_projection(C1, g)
end
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.