Skip to content

Commit c7d5d4e

Browse files
committed
Draft of a better periodic boundary Example
1 parent 601a7ee commit c7d5d4e

2 files changed

Lines changed: 189 additions & 1 deletion

File tree

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#=
2+
3+
# 230 : Periodic Boundary
4+
([source code](@__SOURCE_URL__))
5+
6+
This is a simple demonstration and validation of the generic periodic boundary operator.
7+
8+
We construct a irregular periodic 2D grid grid and solve a simple linear elastic problem.
9+
10+
=#
11+
12+
module Example312_PeriodicBoundary
13+
14+
using ExtendableFEM
15+
using ExtendableGrids
16+
using SimplexGridFactory
17+
using GridVisualize
18+
using TetGen
19+
using UnicodePlots
20+
using StaticArrays
21+
using GLMakie
22+
using LinearAlgebra
23+
using Test #hide
24+
25+
const reg_left = 1
26+
const reg_right = 2
27+
const reg_dirichlet = 3
28+
const reg_default = 4
29+
30+
31+
# define the Hooke tensor for AlN (from DOI 10.1063/1.1368156)
32+
function material_tensor()
33+
c11 = 396.0
34+
c12 = 137.0
35+
c13 = 108.0
36+
c33 = 373.0
37+
c44 = 116.0
38+
39+
40+
return @SArray [
41+
c11 c12 c13 0 0 0
42+
c12 c11 c13 0 0 0
43+
c13 c13 c33 0 0 0
44+
0 0 0 c44 0 0
45+
0 0 0 0 c44 0
46+
0 0 0 0 0 c44
47+
]
48+
end
49+
50+
## generate the kernels for the linear problem
51+
## 𝐂: Hooke tensor, 𝑓: body force
52+
function make_kernels(𝐂, 𝑓)
53+
54+
function bilinear_kernel!(σ, εv, qpinfo)
55+
56+
mul!(σ, 𝐂, εv)
57+
58+
return nothing
59+
end
60+
61+
# rhs is just the (negative) pre-stress
62+
function linear_kernel!(result, qpinfo)
63+
64+
result .= 𝑓
65+
66+
return nothing
67+
end
68+
69+
return bilinear_kernel!, linear_kernel!
70+
end
71+
72+
73+
"""
74+
create a 3×1×1 cuboid with Dirichlet boundary region at the bottom center
75+
"""
76+
function create_grid(; h, height, width, depth)
77+
builder = SimplexGridBuilder(; Generator = TetGen)
78+
79+
## bottom points
80+
b01 = point!(builder, 0, 0, 0)
81+
b02 = point!(builder, 0.45 * width, 0, 0)
82+
b03 = point!(builder, 0.55 * width, 0, 0)
83+
b04 = point!(builder, width, 0, 0)
84+
85+
b11 = point!(builder, 0, depth, 0)
86+
b12 = point!(builder, 0.45 * width, depth, 0)
87+
b13 = point!(builder, 0.55 * width, depth, 0)
88+
b14 = point!(builder, width, depth, 0)
89+
90+
## top points
91+
t01 = point!(builder, 0, 0, height)
92+
t02 = point!(builder, width, 0, height)
93+
94+
t11 = point!(builder, 0, depth, height)
95+
t12 = point!(builder, width, depth, height)
96+
97+
## default faces
98+
facetregion!(builder, reg_default)
99+
facet!(builder, b01, b02, b12, b11)
100+
facet!(builder, b03, b04, b14, b13)
101+
facet!(builder, t01, t02, t12, t11)
102+
facet!(builder, [b01, b02, b03, b04, t02, t01])
103+
facet!(builder, [b11, b12, b13, b14, t12, t11])
104+
105+
## left face
106+
facetregion!(builder, reg_left)
107+
facet!(builder, b01, t01, t11, b11)
108+
109+
## right face
110+
facetregion!(builder, reg_right)
111+
facet!(builder, b04, t02, t12, b14)
112+
113+
## Dirichlet face
114+
facetregion!(builder, reg_dirichlet)
115+
facet!(builder, b02, b03, b13, b12)
116+
117+
cellregion!(builder, 1)
118+
maxvolume!(builder, h)
119+
regionpoint!(builder, width / 2, depth / 2, height / 2)
120+
121+
return simplexgrid(builder)
122+
end
123+
124+
125+
function main(;
126+
order = 1,
127+
periodic = true,
128+
Plotter = GLMakie,
129+
force = 10.0,
130+
h = 1.0e-5,
131+
width = 3.0,
132+
height = 0.1,
133+
depth = 1,
134+
kwargs...
135+
)
136+
137+
xgrid = create_grid(; h, width, height, depth)
138+
139+
## create finite element space and solution vector
140+
if order == 1
141+
FES = FESpace{H1P1{3}}(xgrid)
142+
elseif order == 2
143+
FES = FESpace{H1P2{3, 3}}(xgrid)
144+
end
145+
146+
## problem description
147+
PD = ProblemDescription()
148+
u = Unknown("u"; name = "displacement")
149+
assign_unknown!(PD, u)
150+
151+
𝐂 = material_tensor()
152+
𝑓 = force * [0, 0, 1]
153+
154+
bilinear_kernel!, linear_kernel! = make_kernels(𝐂, 𝑓)
155+
assign_operator!(PD, BilinearOperator(bilinear_kernel!, [εV(u, 1.0)]; kwargs...))
156+
assign_operator!(PD, LinearOperator(linear_kernel!, [id(u)]; kwargs...))
157+
158+
assign_operator!(PD, HomogeneousBoundaryData(u; regions = [reg_dirichlet]))
159+
160+
function give_opposite!(y, x)
161+
y .= x
162+
y[1] = width - x[1]
163+
return nothing
164+
end
165+
166+
if periodic
167+
coupling_matrix = get_periodic_coupling_matrix(FES, xgrid, reg_left, reg_right, give_opposite!)
168+
display(coupling_matrix)
169+
170+
assign_operator!(PD, CombineDofs(u, u, coupling_matrix; kwargs...))
171+
end
172+
173+
## solve
174+
sol = solve(PD, FES; kwargs...)
175+
176+
plt = GridVisualizer(; Plotter, size = (1000, 800))
177+
magnification = 1
178+
displaced_grid = deepcopy(xgrid)
179+
displace_mesh!(displaced_grid, sol[1], magnify = magnification)
180+
gridplot!(plt, displaced_grid, linewidth = 1, title = "displaced mesh, $(magnification)x magnified", scene3d = :LScene)
181+
182+
return sol
183+
184+
end
185+
186+
# TODO generateplots
187+
188+
end # module

src/common_operators/combinedofs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ function build_assembler!(CD::CombineDofs{UT, CT}, FE::Array{<:FEVectorBlock, 1}
115115
# replace sourcerow with coupling linear combination
116116
_addnz(A, sourcerow, sourcerow, -1.0, 1)
117117
for (dof_j, weight) in zip(coupled_dofs, weights)
118-
# set negative weight for dofᵢ - ∑ⱼ wⱼdofⱼ = 0
118+
# weights for ∑ⱼ wⱼdofⱼ - dofᵢ = 0
119119
_addnz(A, sourcerow, dof_j + offsetY, weight, 1)
120120
end
121121

0 commit comments

Comments
 (0)