Add exercise 4

This commit is contained in:
nssc_kuen 2022-06-06 12:51:05 +02:00
förälder 3c77a2e57b
incheckning 392cc3fead
20 ändrade filer med 61430 tillägg och 36 borttagningar

12
Exercise_04/Parameters.jl Normal file
Visa fil

@ -0,0 +1,12 @@
module Parameters
export k, hz, L, q, T, e, elₘ
k = 429.
hz = 0.0005
L = 0.01
q = 2000000.
T = 293.
c = 10.
elₘ = [41,42,43,44,45,46,47,59,60,61,62,63,77,78,79,95]
end

5
Exercise_04/README Normal file
Visa fil

@ -0,0 +1,5 @@
FEM solver
- programmed in julia
- run using `julia run.jl`
- this generates output txt files in ./txt/ and plots in ./plots/ for all 5 variants

104
Exercise_04/fem.jl Normal file
Visa fil

@ -0,0 +1,104 @@
module FEM
export Node, Element, stiffness, tri_tiles, gradient, center, normalize, p
include("./Parameters.jl")
using GeometryBasics
using GeometryBasics.LinearAlgebra
struct Node
x::Float64
y::Float64
index::UInt
end
p(n::Node) = Point2f(n.x, n.y)
struct Element
nodes::Vector{Node}
a::Vector{Float64}
b::Vector{Float64}
c::Vector{Float64}
Δ::Float64
function Element(n::Vector{Node})
xs = map(nd->nd.x,n)
ys = map(nd->nd.y,n)
a = cross(xs, ys)
b = cross(ys, ones(3))
c = cross(ones(3), xs)
Δ = dot(xs,b) / 2
new(n,a,b,c,Δ)
end
end
function stiffness(e::Element)::Matrix{Float64}
# tensor product
Hₑ = e.b .* e.b'
Hₑ += e.c .* e.c'
Hₑ *= Parameters.hz*Parameters.k/4e.Δ
return Hₑ
end
function tri_tiles(L::Float64, divisions::Int, trapezoidal::Bool=false, biased::Bool=false, ring::Bool=false)::Tuple{Vector{Node}, Vector{Element}}
nodes = Matrix{Node}(undef, divisions+1, divisions+1)
i = 1
for y in 0:divisions
for x in 0:divisions
xₑ = L*x/divisions
yₑ = L*y/divisions
if biased
B = yₑ/2Parameters.L
xₑ = xₑ*(xₑ*B/Parameters.L - B + 1)
end
if trapezoidal
xₑ *= 1 - 0.5*(y/divisions)
end
if ring
r = Parameters.L*(1 + x/divisions)
θ = (π/4)*(y/divisions)
xₑ = r*cos(θ)
yₑ = r*sin(θ)
xₑ -= Parameters.L
end
nodes[x+1,y+1] = Node(xₑ,yₑ,i)
i += 1
end
end
elements = []
for y in 1:divisions
for x in 1:divisions
# lower/upper triangle
push!(elements, Element([nodes[x,y], nodes[x+1,y], nodes[x,y+1]]))
push!(elements, Element([nodes[x+1,y+1], nodes[x,y+1], nodes[x+1,y]]))
end
end
return vec(nodes), elements
end
function gradient(e::Element, T::Vector{Float64})::Vec2f
return Vec2f([
e.b[1] e.b[2] e.b[3] ;
e.c[1] e.c[2] e.c[3]
] * [
T[e.nodes[1].index]
T[e.nodes[2].index]
T[e.nodes[3].index]
] / 2e.Δ)
end
center(e::Element)::Point2f = Point2f(sum([n.x for n in e.nodes])/3.0, sum([n.y for n in e.nodes])/3.0)
normalize(v::Vec2f)::Vec2f = v / sqrt(v[1]^2 + v[2]^2)
end

0
Exercise_04/plots/.keep Normal file
Visa fil

Binär
Exercise_04/plots/baseline.png (Sparad med Git LFS) Normal file

Binary file not shown.

Binär
Exercise_04/plots/variation1.png (Sparad med Git LFS) Normal file

Binary file not shown.

Binär
Exercise_04/plots/variation2.png (Sparad med Git LFS) Normal file

Binary file not shown.

Binär
Exercise_04/plots/variation3.png (Sparad med Git LFS) Normal file

Binary file not shown.

Binär
Exercise_04/plots/variation4_div.png (Sparad med Git LFS) Normal file

Binary file not shown.

Binär
Exercise_04/plots/variation4_mul.png (Sparad med Git LFS) Normal file

Binary file not shown.

39
Exercise_04/print_HTP.jl Normal file
Visa fil

@ -0,0 +1,39 @@
using Fmt
function print_HTP(H::Matrix{Float64}, T::Vector{Float64}, P::Vector{Float64}, filename="output.txt")
# Print matrices to .txt-file (name of file = filename).
# H... overall assembled stiffness matrix
# T... nodal temperature vector
# P... nodal force vector
# Make sure, that your system of equations is sorted by
# ascending node numbers, i.e., N1 N2 ... N100.
open(filename, "w") do io
write(io, "Stiffness matrix H: \n")
for row in H
for col in row
outline = f"{$col:+8.4e},"
write(io, f"{$outline:11s}")
end
write(io, "\n")
end
write(io, "Temperature T: \n")
for row in T
for col in row
outline = f"{$col:+8.4e},"
write(io, f"{$outline:11s} \n")
end
end
write(io, "Force vector P: \n")
for row in P
for col in row
outline = f"{$col:+8.4e},"
write(io, f"{$outline:11s} \n")
end
end
end
end

Visa fil

@ -1,36 +0,0 @@
def print_HTP(H, T, P, filename="output.txt"):
"""
Print matrices to .txt-file (name of file = filename).
H... overall assembled stiffness matrix
T... nodal temperature vector
P... nodal force vector
Make sure, that your system of equations is sorted by
ascending node numbers, i.e., N1 N2 ... N100.
"""
F = open(filename, 'w')
F.write("Stiffness matrix H: \n")
for row in H:
for col in row:
outline = "{0:+8.4e},".format(col)
F.write("{0:11s}".format(str(outline)))
F.write("\n")
F.write("Temperature T: \n")
for row in T:
for col in row:
outline = "{0:+8.4e},".format(col)
F.write("{0:11s} \n".format(str(outline)))
F.write("Force vector P: \n")
for row in P:
for col in row:
outline = "{0:+8.4e},".format(col)
F.write("{0:11s} \n".format(str(outline)))
F.close()
return None

94
Exercise_04/run.jl Normal file
Visa fil

@ -0,0 +1,94 @@
include("./fem.jl")
include("./Parameters.jl")
include("./print_HTP.jl")
using .FEM
using GLMakie
using Makie.GeometryBasics
@enum Variation BASIC V1 V2 V3 V4_div V4_mul
function solve(name::String, variation::Variation)
div = 9
H = zeros(Float64,(div+1)^2, (div+1)^2)
(nodes, elements) = tri_tiles(Parameters.L, div, variation==V1, variation==V2, variation==V3)
for (index, el) in enumerate(elements)
Hₑ = stiffness(el)
if variation == V4_div && index in Parameters.elₘ
Hₑ /= Parameters.c
elseif variation == V4_mul && index in Parameters.elₘ
Hₑ *= Parameters.c
end
for i in 1:3
for j in 1:3
H[el.nodes[i].index, el.nodes[j].index] += Hₑ[i,j]
end
end
end
P = zeros(Float64, 90)
# impose neumann conditions on top edge
# adapted from https://mathoverflow.net/questions/5085/how-to-apply-neuman-boundary-condition-to-finite-element-method-problems
# maybe check if this actually makes sense
nᵧ = -Parameters.q / Parameters.k
# skip=2 since only every second element has a edge along the bottom: ◺◹
for ∂_el in elements[1:2:18]
n1 = ∂_el.nodes[1]
n2 = ∂_el.nodes[2]
l = abs(n2.x - n1.x)
P[n1.index] += nᵧ*l/2
P[n2.index] += nᵧ*l/2
end
rhs = P - H[1:90,91:100]*fill(Parameters.T, 10,1)
T = vec(H[1:90,1:90]\rhs)
append!(T, fill(Parameters.T, 10))
reaction_forces = H[91:100,:]*T
centers = center.(elements)
gradients = map(el -> gradient(el, T), elements)
flux = gradients .* -1
norm = maximum(map(g-> sqrt(g[1]^2 + g[2]^2), gradients))/(Parameters.L/div)*2.5
gradients ./= norm
flux ./= norm
set_theme!(theme_black())
f = Figure(resolution = (1536, 1024))
tris = map(e->Polygon([p(e.nodes[1]), p(e.nodes[2]), p(e.nodes[3])]), elements)
poly(f[1, 1], tris, color=:transparent, linestyle=:solid, strokewidth=0.8, strokecolor=:white, transparency=true)
xs = map(n->n.x, nodes)
ys = map(n->n.y, nodes)
xs = reshape(xs, (div+1, div+1))
ys = reshape(ys, (div+1, div+1))
Ts = reshape(T, (div+1, div+1))
surface(f[2, 1], xs, ys, Ts, colormap=:matter, axis=(type=Axis3,))
contour(f[1:2,2:3], map(n->n.x,nodes), map(n->n.y,nodes), T, levels=16, colormap=:matter)
arrows!(f[1:2,2:3], centers, gradients, arrowcolor=:red, linecolor=:red)
arrows!(f[1:2,2:3], centers, flux, arrowcolor=:blue, linecolor=:blue)
save("plots/$name.png", current_figure())
print_HTP(H, T, P, "txt/htp_$name.txt")
end
solve("baseline", BASIC)
solve("variation1", V1)
solve("variation2", V2)
solve("variation3", V3)
solve("variation4_div", V4_div)
solve("variation4_mul", V4_mul)

0
Exercise_04/txt/.keep Normal file
Visa fil

Filskillnaden har hållits tillbaka eftersom den är för stor Load Diff

Filskillnaden har hållits tillbaka eftersom den är för stor Load Diff

Filskillnaden har hållits tillbaka eftersom den är för stor Load Diff

Filskillnaden har hållits tillbaka eftersom den är för stor Load Diff

Filskillnaden har hållits tillbaka eftersom den är för stor Load Diff

Filskillnaden har hållits tillbaka eftersom den är för stor Load Diff