Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing 3D no-slip boundary condition #187

Merged
merged 21 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ makedocs(;
"Installation" => "man/installation.md",
"Backend" => "man/backend.md",
"Equations" => "man/equations.md",
"Boundary conditions" => "man/boundary_conditions.md",
"Advection" => "man/advection.md",
],
"Examples" => Any[
Expand Down
36 changes: 36 additions & 0 deletions docs/src/man/boundary_conditions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Flow boundary conditions

Supported boundary conditions:

1. Free slip

$\frac{\partial u_i}{\partial x_i} = 0$ at the boundary $\Gamma$

2. No slip

$u_i = 0$ at the boundary $\Gamma$

3. Free surface

$\sigma_z = 0 \rightarrow \tau_z = P$ at the top boundary

## Defining the boundary contions
Information regarding flow boundary conditions is defined in the `FlowBoundaryConditions` object. They can be switched on and off by setting them as `true` or `false` at the appropriate boundaries. Valid boundary names are `left` and `right`, `top` and `bot`, and for the 3D case, `front` and `back`.

For example, if we want to have free free-slip in every single boundary in a 2D simulation, we need to instantiate `FlowBoundaryConditions` as:
```julia
bcs = FlowBoundaryConditions(;
no_slip = (left=false, right=false, top=false, bot=false),
free_slip = (left=true, right=true, top=true, bot=true),
free_surface = false
)
```

The equivalent for the 3D case would be:
```julia
bcs = FlowBoundaryConditions(;
no_slip = (left=false, right=false, top=false, bot=false, front=false, back=false),
free_slip = (left=true, right=true, top=true, bot=true, front=true, back=true),
free_surface = false
)
```
55 changes: 55 additions & 0 deletions src/boundaryconditions/no_slip.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,58 @@
end
return nothing
end

@parallel_indices (i, j) function no_slip!(Ax, Ay, Az, bc)
@inbounds begin
if bc.left
(i ≤ size(Ax, 2)) && (j ≤ size(Ax, 3)) && (Ax[1, i, j] = 0.0)
(1 < i < size(Ay, 2)) && (1 < j < size(Ay, 3)) && (Ay[1, i, j] = -Ay[2, i, j])
(1 < i < size(Az, 2)) && (1 < j < size(Az, 3)) && (Az[1, i, j] = -Az[2, i, j])
end
if bc.right
(i ≤ size(Ax, 2)) && (j ≤ size(Ax, 3)) && (Ax[end, i, j] = 0.0)
(1 < i < size(Ay, 2)) &&
(1 < j < size(Ay, 3)) &&
(Ay[end, i, j] = -Ay[end - 1, i, j])
(1 < i < size(Az, 2)) &&
(1 < j < size(Az, 3)) &&
(Az[end, i, j] = -Az[end - 1, i, j])
end

if bc.front
(i ≤ size(Ay, 1)) && (i ≤ size(Ay, 2)) && (Ay[i, 1, j] = 0.0)
(1 < i < size(Ax, 1)) && (1 < j < size(Ax, 3)) && (Ax[i, 1, j] = -Ax[i, 2, j])
(1 < i < size(Az, 1)) && (1 < j < size(Az, 3)) && (Az[i, 1, j] = -Az[i, 2, j])
end
if bc.back
(i ≤ size(Ay, 1)) && (i ≤ size(Ay, 2)) && (Ay[i, end, j] = 0.0)
(1 < i < size(Ax, 1)) &&
(1 < j < size(Ax, 3)) &&
(Ax[i, end, j] = -Ax[i, end - 1, j])
(1 < i < size(Az, 1)) &&
(1 < j < size(Az, 3)) &&
(Az[i, end, j] = -Az[i, end - 1, j])
end

if bc.bot
(i ≤ size(Az, 1)) && (j ≤ size(Az, 3)) && (Az[i, j, 1] = 0.0)
(1 < i < size(Ax, 1)) && (1 < j < size(Ax, 2)) && (Ax[i, j, 1] = -Ax[i, j, 2])
(1 < i < size(Ay, 1)) && (1 < j < size(Ay, 2)) && (Ay[i, j, 1] = -Ay[i, j, 2])
end
if bc.top
(i ≤ size(Az, 1)) && (j ≤ size(Az, 3)) && (Az[i, j, end] = 0.0)
(1 < i < size(Ax, 1)) &&
(1 < j < size(Ax, 2)) &&
(Ax[i, j, end] = -Ax[i, j, end - 1])
(1 < i < size(Ay, 1)) &&
(1 < j < size(Ay, 2)) &&
(Ay[i, j, end] = -Ay[i, j, end - 1])
end

# corners
# bc.bot && (Ax[1, 1] = 0.0; Ax[1, 1] = 0.0)
# bc.left && bc.bot && (Ax[1, 1] = 0.0)
# bc.right && bc.top && (Ay[end, end] = 0.0)
end
return nothing
end
17 changes: 11 additions & 6 deletions src/stokes/Stokes3D.jl
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,15 @@ function _solve!(
iter += 1
if iter % nout == 0 && iter > 1
cont += 1
push!(norm_Rx, maximum_mpi(abs.(stokes.R.Rx)))
push!(norm_Ry, maximum_mpi(abs.(stokes.R.Ry)))
push!(norm_Rz, maximum_mpi(abs.(stokes.R.Rz)))
push!(norm_∇V, maximum_mpi(abs.(stokes.R.RP)))
# push!(norm_Rx, maximum_mpi(abs.(stokes.R.Rx)))
# push!(norm_Ry, maximum_mpi(abs.(stokes.R.Ry)))
# push!(norm_Rz, maximum_mpi(abs.(stokes.R.Rz)))
# push!(norm_∇V, maximum_mpi(abs.(stokes.R.RP)))
push!(norm_Rx, norm_mpi(stokes.R.Rx) / length(stokes.R.Rx))
push!(norm_Ry, norm_mpi(stokes.R.Ry) / length(stokes.R.Ry))
push!(norm_Rz, norm_mpi(stokes.R.Rz) / length(stokes.R.Rz))
push!(norm_∇V, norm_mpi(stokes.R.RP) / length(stokes.R.RP))

err = max(norm_Rx[cont], norm_Ry[cont], norm_Rz[cont], norm_∇V[cont])
push!(err_evo1, err)
push!(err_evo2, iter)
Expand Down Expand Up @@ -488,9 +493,9 @@ function _solve!(
if iter % nout == 0 && iter > 1
cont += 1
for (norm_Ri, Ri) in zip((norm_Rx, norm_Ry, norm_Rz), @residuals(stokes.R))
push!(norm_Ri, maximum(abs.(Ri)))
push!(norm_Ri, norm_mpi(Ri) / length(Ri))
end
push!(norm_∇V, maximum(abs.(stokes.R.RP)))
push!(norm_∇V, norm_mpi(stokes.R.RP) / length(stokes.R.RP))
err = max(norm_Rx[cont], norm_Ry[cont], norm_Rz[cont], norm_∇V[cont])
push!(err_evo1, err)
push!(err_evo2, iter)
Expand Down
91 changes: 91 additions & 0 deletions test/test_boundary_conditions3D.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
@static if ENV["JULIA_JUSTRELAX_BACKEND"] === "AMDGPU"
using AMDGPU
elseif ENV["JULIA_JUSTRELAX_BACKEND"] === "CUDA"
using CUDA
end

using JustRelax, JustRelax.JustRelax3D
using Test, Suppressor

const backend = @static if ENV["JULIA_JUSTRELAX_BACKEND"] === "AMDGPU"
AMDGPUBackend
elseif ENV["JULIA_JUSTRELAX_BACKEND"] === "CUDA"
CUDABackend
else
CPUBackend
end

@testset "Boundary Conditions" begin
if backend === CPUBackend
@suppress begin

# test incompatible boundary conditions
@test_throws ErrorException FlowBoundaryConditions(;
no_slip = (left=true, right=true, front=true, back=true, top=true, bot=true),
free_slip = (left=false, right=true, front=true, back=true, top=true, bot=true),
)


# test with StokesArrays
ni = 5, 5, 5
stokes = StokesArrays(backend, ni)
stokes.V.Vx .= PTArray(backend)(rand(size(stokes.V.Vx)...))
stokes.V.Vy .= PTArray(backend)(rand(size(stokes.V.Vy)...))
stokes.V.Vz .= PTArray(backend)(rand(size(stokes.V.Vz)...))

# free-slip
flow_bcs = FlowBoundaryConditions(;
no_slip = (left=false, right=false, front=false, back=false, top=false, bot=false),
free_slip = (left=true, right=true, front=true, back=true, top=true, bot=true),
)
flow_bcs!(stokes, flow_bcs)

@test @views stokes.V.Vx[ :, :, 1] == stokes.V.Vx[:, :, 2]
@test @views stokes.V.Vx[ :, :, end] == stokes.V.Vx[:, :, end - 1]
@test @views stokes.V.Vx[ :, 1, :] == stokes.V.Vx[:, 2, :]
@test @views stokes.V.Vx[ :, end, :] == stokes.V.Vx[:, end - 1, :]
@test @views stokes.V.Vy[ :, :, 1] == stokes.V.Vy[:, :, 2]
@test @views stokes.V.Vy[ :, :, end] == stokes.V.Vy[:, :, end - 1]
@test @views stokes.V.Vy[ 1, :, :] == stokes.V.Vy[2, :, :]
@test @views stokes.V.Vy[end, :, :] == stokes.V.Vy[end - 1, :, :]
@test @views stokes.V.Vz[ 1, :, :] == stokes.V.Vz[2, :, :]
@test @views stokes.V.Vz[end, :, :] == stokes.V.Vz[end - 1, :, :]
@test @views stokes.V.Vz[ :, 1, :] == stokes.V.Vz[:, 2, :]
@test @views stokes.V.Vz[ :, end, :] == stokes.V.Vz[:, end - 1, :]

# no-slip
flow_bcs = FlowBoundaryConditions(;
no_slip = (left=true, right=true, front=true, back=true, top=true, bot=true),
free_slip = (left=false, right=false, front=false, back=false, top=false, bot=false),
)
flow_bcs!(stokes, flow_bcs)

(; Vx, Vy, Vz) = stokes.V

@test sum(!iszero(Vx[1 , i, j]) for i in axes(Vx,2)[2:end-1], j in axes(Vx,3)[2:end-1]) == 0
@test sum(!iszero(Vx[end, i, j]) for i in axes(Vx,2)[2:end-1], j in axes(Vx,3)[2:end-1]) == 0
@test sum(!iszero(Vy[i, 1, j]) for i in axes(Vy,1)[2:end-1], j in axes(Vy,3)[2:end-1]) == 0
@test sum(!iszero(Vy[i, end, j]) for i in axes(Vy,1)[2:end-1], j in axes(Vy,3)[2:end-1]) == 0
@test sum(!iszero(Vz[i, j, 1]) for i in axes(Vz,1)[2:end-1], j in axes(Vz,3)[2:end-1]) == 0
@test sum(!iszero(Vz[i, j, end]) for i in axes(Vz,1)[2:end-1], j in axes(Vz,3)[2:end-1]) == 0


@test @views Vx[2:end-1, 1, 2:end-1] == -Vx[2:end-1, 2, 2:end-1]
@test @views Vx[2:end-1, end, 2:end-1] == -Vx[2:end-1, end - 1, 2:end-1]
@test @views Vx[2:end-1, 2:end-1, 1] == -Vx[2:end-1, 2:end-1, 2]
@test @views Vx[2:end-1, 2:end-1, end] == -Vx[2:end-1, 2:end-1, end - 1]

@test @views Vy[1 , 2:end-1, 2:end-1] == -Vy[2 , 2:end-1, 2:end-1]
@test @views Vy[end , 2:end-1, 2:end-1] == -Vy[end - 1, 2:end-1, 2:end-1]
@test @views Vy[2:end-1, 2:end-1, 1] == -Vy[2:end-1, 2:end-1, 2]
@test @views Vy[2:end-1, 2:end-1, end] == -Vy[2:end-1, 2:end-1, end - 1]

@test @views Vz[2:end-1, 1, 2:end-1] == -Vz[2:end-1, 2, 2:end-1]
@test @views Vz[2:end-1, end, 2:end-1] == -Vz[2:end-1, end - 1, 2:end-1]
@test @views Vz[ 1, 2:end-1, 2:end-1] == -Vz[ 2, 2:end-1, 2:end-1]
@test @views Vz[ end, 2:end-1, 2:end-1] == -Vz[end - 1, 2:end-1, 2:end-1]
end
else
@test true === true
end
end
Loading