defining basis. still needs some rethinking...

This commit is contained in:
Jukka Aho
2015-11-02 21:25:02 +02:00
parent a80544a783
commit 75e6ed8fcb
6 changed files with 382 additions and 107 deletions
+157 -31
View File
@@ -5,9 +5,163 @@ module BasisTests
using JuliaFEM.Test
using JuliaFEM: get_basis, grad, FieldSet, Field, Quad4
using JuliaFEM
using JuliaFEM: Basis, ElementGradientBasis, ElementFieldGradientBasis, Field
function get_basis()
basis(xi) = 1/4*[
(1-xi[1])*(1-xi[2])
(1+xi[1])*(1-xi[2])
(1+xi[1])*(1+xi[2])
(1-xi[1])*(1+xi[2])]'
dbasis(xi) = 1/4*[
-(1-xi[2]) (1-xi[2]) (1+xi[2]) -(1+xi[2])
-(1-xi[1]) -(1+xi[1]) (1+xi[1]) (1-xi[1])]
return basis, dbasis
end
function test_basic_interpolation()
basis, dbasis = get_basis()
b = Basis(basis, dbasis)
@test b([0.0, 0.0]) == 1/4*[1 1 1 1]
@test b([0.0, 0.0], 1.0) == 1/4*[1 1 1 1]
end
function test_basic_interpolation_of_field()
# in unit square: T(X,t) = t*(1 + X[1] + 3*X[2] - 2*X[1]*X[2])
temperature = Field(
(0.0, [0.0, 0.0, 0.0, 0.0]),
(1.0, [1.0, 2.0, 3.0, 4.0]))
basis, dbasis = get_basis()
b = Basis(basis, dbasis, temperature)
T(X,t) = t*(1 + X[1] + 3*X[2] - 2*X[1]*X[2])
@test b([0.0, 0.0], 0.0) == T([0.5, 0.5], 0.0)
@test b([0.0, 0.0], 0.6) == T([0.5, 0.5], 0.6)
@test b([0.0, 0.0], 1.0) == T([0.5, 0.5], 1.0)
end
function test_linear_time_extrapolation_of_field()
temperature = Field(
(0.0, [0.0, 0.0, 0.0, 0.0]),
(1.0, [1.0, 2.0, 3.0, 4.0]))
basis, dbasis = get_basis()
b = Basis(basis, dbasis, temperature, :linear)
T(X,t) = t*(1 + X[1] + 3*X[2] - 2*X[1]*X[2])
@test b([0.0, 0.0], -1.0) == T([0.5, 0.5], -1.0)
@test b([0.0, 0.0], 3.0) == T([0.5, 0.5], 3.0)
end
function test_constant_time_extrapolation_of_field()
temperature = Field(
(0.0, [0.0, 0.0, 0.0, 0.0]),
(1.0, [1.0, 2.0, 3.0, 4.0]))
basis, dbasis = get_basis()
b = Basis(basis, dbasis, temperature, :constant)
T(X,t) = t*(1 + X[1] + 3*X[2] - 2*X[1]*X[2])
@test b([0.0, 0.0], -1.0) == T([0.5, 0.5], 0.0)
@test b([0.0, 0.0], 3.0) == T([0.5, 0.5], 1.0)
end
function test_time_extrapolation_of_field_with_single_timestep()
temperature = Field([1.0, 2.0, 3.0, 4.0])
basis, dbasis = get_basis()
b = Basis(basis, dbasis, temperature)
@test b([0.0, 0.0], 1.0) == mean([1.0, 2.0, 3.0, 4.0])
end
function test_gradient_interpolation_empty_gradient()
X = [0.0 0.0; 1.0 0.0; 1.0 1.0; 0.0 1.0]'
geometry = Field(X)
# P(X) = [1.0, X[1], X[2], X[1]*X[2]]
# basis2, dbasis2 = JuliaFEM.calculate_lagrange_basis(P, X)
basis, dbasis = get_basis()
N = Basis(basis, dbasis)
dN = ElementGradientBasis(N, geometry)
@test dN([0.0, 0.0]) == 1/2*[-1 1 1 -1; -1 -1 1 1]
# @test dN([0.0, 0.0]) == dbasis2([0.5, 0.5])
end
function test_gradient_interpolation_of_scalar_field()
# in unit square: grad(T)(X) = [1-2X[2], 3-2*X[1]]
geometry = Field([0.0 0.0; 1.0 0.0; 1.0 1.0; 0.0 1.0]')
temperature = Field([1, 2, 3, 4])
basis, dbasis = get_basis()
N = Basis(basis, dbasis)
dN = ElementGradientBasis(N, geometry)
dT = ElementFieldGradientBasis(dN, temperature)
dT_expected(X) = [1-2*X[2] 3-2*X[1]]
@test dT([0.0, 0.0]) == dT_expected([0.5, 0.5])
end
function test_interpolation_of_vector_field()
# in unit square, u(X,t) = [1/4*t*X[1]*X[2], 0, 0]
geometry = Field([0.0 0.0; 1.0 0.0; 1.0 1.0; 0.0 1.0]')
displacement = Field(
(0.0, Vector[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]),
(1.0, Vector[[0.0, 0.0], [0.0, 0.0], [1/4, 0.0], [0.0, 0.0]]))
basis, dbasis = get_basis()
X = Basis(basis, dbasis, geometry)
u = Basis(basis, dbasis, displacement)
u_expected(X,t) = [1/4*t*X[1]*X[2], 0]
# x = X + u
x = X([0.0, 0.0], 1.0) + u([0.0, 0.0], 1.0)
@test isapprox(x, [9/16, 1/2])
@test isapprox(u([0.0, 0.0], 1.0), u_expected([0.5, 0.5], 1.0))
end
function test_interpolation_of_gradient_of_vector_field()
# in unit square, u(X) = t*[X[1]*X[2]/4, X[1]*(X[1]+X[2])/2]
# => u_i,j = t*[X[2]/4 X[1]/4; X[1]/2+(X[1]+X[2])/2 X[1]/2]
geometry = Field([0.0 0.0; 1.0 0.0; 1.0 1.0; 0.0 1.0]')
displacement = Field(
(0.0, Vector[[0.0, 0.0], [0.0, 0.0], [0.00, 0.0], [0.0, 0.0]]),
(1.0, Vector[[0.0, 0.0], [0.0, 0.5], [0.25, 1.0], [0.0, 0.0]]))
basis, dbasis = get_basis()
N = Basis(basis, dbasis)
dN = ElementGradientBasis(N, geometry)
dU = ElementFieldGradientBasis(dN, displacement)
dU_expected(X, t) = t*[X[2]/4 X[1]/4; X[1]/2+(X[1]+X[2])/2 X[1]/2]
@test isapprox(dU([0.0, 0.0], 1.0), dU_expected([0.5, 0.5], 1.0))
end
# TODO: how on earth make this work without some serious spaghetti code
function test_time_derivative_gradient_interpolation_of_field()
# in unit square, u(X) = t*[X[1]*X[2]/4, X[1]*(X[1]+X[2])/2]
# => u_i,j = t*[X[2]/4 X[1]/4; X[1]/2+(X[1]+X[2])/2 X[1]/2]
# => d(u_i,j)/dt = [X[2]/4 X[1]/4; X[1]/2+(X[1]+X[2])/2 X[1]/2]
geometry = Field([0.0 0.0; 1.0 0.0; 1.0 1.0; 0.0 1.0]')
displacement = Field(
(0.0, Vector[[0.0, 0.0], [0.0, 0.0], [0.00, 0.0], [0.0, 0.0]]),
(1.0, Vector[[0.0, 0.0], [0.0, 0.5], [0.25, 1.0], [0.0, 0.0]]))
basis, dbasis = get_basis()
N = Basis(basis, dbasis)
# wanted
#u = Basis(basis, dbasis, displacement)
#L = grad(diff(u))
#D = 1/2*(L + L')
#@text isapprox(D([0.0, 0.0], 1.0), ...)
xi = [0.0, 0.0]
time = 1.0
grad = ElementGradientBasis(N, geometry)(xi, time)
increment = displacement(time, Val{:derivative}, :linear, :linear)
diffgradu = sum([grad[:,i]*increment[i]' for i=1:length(increment)])'
diffgradu_expected(X, t) = [X[2]/4 X[1]/4; X[1]/2+(X[1]+X[2])/2 X[1]/2]
@test diffgradu == diffgradu_expected([0.5, 0.5], 1.0)
end
#=
"""basic continuum interpolations"""
function test_basic_interpolations()
@@ -42,10 +196,9 @@ function test_basic_interpolations()
@test isapprox(U, [1.24235 0.13804; 0.13804 1.02149])
end
=#
function test_interpolation_in_temporal_basis()
info("testing interpolation on temporal basis")
temporalbasis = TemporalBasis((t) -> [1-t, t], (t) -> [-1, 1])
@test temporalbasis(0.2) == [0.8, 0.2]
i1 = Increment([0.0])
i2 = Increment([1.0])
i3 = Increment([2.0])
@@ -90,31 +243,4 @@ function test_interpolation_in_temporal_basis()
@test isa(velocity, Increment) == true
end
function test_interpolation_in_spatial_basis()
info("testing interpolation on spatial basis")
basis(xi) = 1/4*[
(1-xi[1])*(1-xi[2])
(1+xi[1])*(1-xi[2])
(1+xi[1])*(1+xi[2])
(1-xi[1])*(1+xi[2])]'
dbasis(xi) = 1/4*[
-(1-xi[2]) (1-xi[2]) (1+xi[2]) -(1+xi[2])
-(1-xi[1]) -(1+xi[1]) (1+xi[1]) (1-xi[1])]
spatialbasis = SpatialBasis(basis, dbasis)
@test spatialbasis.basis([0.0, 0.0]) == 1/4*[1 1 1 1]
fs = FieldSet()
fs["geometry"] = Vector{Float64}[[0.0,0.0], [1.0,0.0], [1.0,1.0], [0.0,1.0]]
fs["displacement"] = (0.0, zeros(2, 4)), (1.0, Vector[[0.0, 0.0], [0.0, 0.0], [0.25, 0.0], [0.0, 0.0]])
X = call(last(fs["geometry"]), spatialbasis, [0.0, 0.0])
u = call(last(fs["displacement"]), spatialbasis, [0.0, 0.0])
x = X+u
@test X ≈ 1/2*[1, 1]
@test x ≈ [9/16, 1/2]
gradu = call(last(fs["displacement"]), spatialbasis, [0.0, 0.0], last(fs["geometry"]), Val{:gradient})
@test gradu ≈ [0.125 0.125; 0.0 0.0]
end
end
+18 -6
View File
@@ -6,8 +6,7 @@ module FieldTests
using JuliaFEM
using JuliaFEM: Increment, TimeStep, Field, DefaultDiscreteField, FieldSet
using JuliaFEM: TemporalBasis, SpatialBasis, ContinuousField, DiscreteField
using JuliaFEM: DefaultContinuousField
using JuliaFEM: ContinuousField, DiscreteField, DefaultContinuousField
using JuliaFEM.Test
@@ -189,7 +188,9 @@ function test_default_discrete_field_quick_way_two_timesteps_with_vector_value()
end
function test_default_discrete_field_quick_way_set_time_vector_also()
f1 = DefaultDiscreteField( (0.5, [1, 2, 3]), (1.0, [3, 4, 5]) )
f1 = DefaultDiscreteField(
(0.5, [1, 2, 3]),
(1.0, [3, 4, 5]))
@test isa(f1[1], TimeStep)
@test isa(f1[2], TimeStep)
@test isa(f1[1][1], Increment)
@@ -200,6 +201,20 @@ function test_default_discrete_field_quick_way_set_time_vector_also()
@test f1[2].time == 1.0
end
function test_default_discrete_field_for_loop()
field = DefaultDiscreteField(
(0.5, [1, 2, 3]),
(1.0, [3, 4, 5]),
(1.5, [4, 5, 6]))
timesteps = [ts for ts in field]
@test timesteps[1].time == 0.5
@test timesteps[2].time == 1.0
@test timesteps[3].time == 1.5
@test timesteps[1][end] == [1, 2, 3]
@test timesteps[2][end] == [3, 4, 5]
@test timesteps[3][end] == [4, 5, 6]
end
function test_default_continuous_field()
function myfield(xi::Vector, time::Float64)
@@ -244,13 +259,10 @@ function test_adding_timesteps()
fs = FieldSet()
fs["temperature"] = [1, 2, 3, 4]
T0 = last(fs["temperature"]) # last increment of last field
@debug("last temperature T0 = $T0")
T1 = Increment(T0 + 1)
@debug("typeof T1 = $(typeof(T1))")
timestep = TimeStep(1.0, Increment[T1]) # new list of increments for timestep
push!(fs["temperature"], timestep)
T2 = last(fs["temperature"])
@debug("last temperature T2 = $T2")
@test length(fs["temperature"]) == 2
@test last(fs["temperature"]) == [2, 3, 4, 5]
@test fs["temperature"][end].time == 1.0