xxxxxxxxxxbegin ENV["LANG"]="C" using Pkg Pkg.activate(mktempdir()) Pkg.add(["PyPlot","PlutoUI","ExtendableGrids","GridVisualize","VoronoiFVM"]) using PlutoUI,PyPlot,ExtendableGrids,VoronoiFVM,GridVisualize PyPlot.svg(true)end;Working with VoronoiFVM.jl
We show how to define scalar linear and nonlinear diffusion problems in the VoronoiFVM package.
In general, the package allows to work with multiple species, so all constitutive functions and the solution array need to handle species indices.
For more information, see its documentation.
Linear diffusion problem with Dirichlet boundary conditions
Regard
The following data characterize the problem:
Flux
Dirichlet data
Source/sink term
Domain
These can be replaced by the following discretization data:
Diffusion coefficient
10.0D=10.0Diffusion flux
The following function receives the parameters in _u. This is an array containing the unkowns unknowns method extracts the unknowns from _u, creatimg a two-dimensional array, where the first parameter is the species index and the second the local number of the node wrt. the edge. The result is written into f for species index 1.
diffusion_flux! (generic function with 1 method)xxxxxxxxxxfunction diffusion_flux!(f,_u, edge) u=unknowns(edge,_u) spec_idx=1 f[spec_idx]=D*(u[spec_idx,1]-u[spec_idx,2])endRight hand side function
diffusion_source! (generic function with 1 method)function diffusion_source!(f,node) f[1]=1endDiscretization grid
Grid in domain
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0
xxxxxxxxxxX=collect(range(0,1,length=N))ExtendableGrids.ExtendableGrid{Float64,Int32};
dim: 1 nodes: 11 cells: 10 bfaces: 2
grid1d=simplexgrid(X)xxxxxxxxxxgridplot(grid1d,Plotter=PyPlot,resolution=(600,200))System creation and solution methods
The problem description is subdivided in two parts: the discretization grid which is used to define the Voronoi cells and the form factors, and the physics part containing the constitutive functions, like the fluxes between neigboring species, the source term, and, possibly, more.
create_system (generic function with 1 method)function create_system(grid,flux, source) physics=VoronoiFVM.Physics(num_species=1,flux=flux,source=source) # physics object system=VoronoiFVM.System(grid,physics) # system object enable_species!(system,1,[1]) systemendAfter setting boundary conditions, we can solve the system. Dirichlet boundary conditions are implemented by the penalty method.
mysolve (generic function with 1 method)xxxxxxxxxxfunction mysolve(system, ul,ur; bcl=1, bcr=2) boundary_dirichlet!(system, 1, bcl,ul) # Set left Dirichlet boundary conditions boundary_dirichlet!(system, 1, bcr,ur) # Set right Dirichlet boundary conditions inival=unknowns(system,inival=0.5*(ul+ur)) # constant initial value VoronoiFVM.solve(inival,system,log=true) # Return a pair (solution, history) when log=trueendSet the Dirichlet boundary data:
u_L=0.01 u_R=0.01
1D Linear diffusion
VoronoiFVM.DenseSystem{Float64,Int32,Int32}(num_species=1)
xxxxxxxxxxsystem1d=create_system(grid1d,diffusion_flux!,diffusion_source!)Using default settings, the system is solved.
1×11 Array{Float64,2}:
0.01 0.0145 0.018 0.0205 0.022 0.0225 0.022 0.0205 0.018 0.0145 0.010.0125
4.48253e-18
xxxxxxxxxx(solution,history)=mysolve(system1d,u_L,u_R)xxxxxxxxxxscalarplot(grid1d,solution[1,:],Plotter=PyPlot,resolution=(600,300))2D Linear diffusion
For solving a 2D problem, we just need to replace the 1D grid with a 2D grid.
ExtendableGrids.ExtendableGrid{Float64,Int32};
dim: 2 nodes: 121 cells: 200 bfaces: 40
x
grid2d=simplexgrid(X,X)xxxxxxxxxxgridplot(grid2d,Plotter=PyPlot)VoronoiFVM.DenseSystem{Float64,Int32,Int32}(num_species=1)
xxxxxxxxxxsystem2d=create_system(grid2d,diffusion_flux!,diffusion_source!)By default, the left boundary is marked by 4 and the right boundary is marked by 2, and we pass the data this way.
1×121 Array{Float64,2}:
0.01 0.0145 0.018 0.0205 0.022 0.0225 … 0.022 0.0205 0.018 0.0145 0.010.0125
1.90069e-17
xxxxxxxxxxsolution2d,history2d=mysolve(system2d,u_L,u_R,bcl=4, bcr=2)xxxxxxxxxxscalarplot(grid2d,solution2d[1,:],Plotter=PyPlot,resolution=(300,300),fignumber=2)Nonlinear diffusion
Here, we define a nonlinear diffusion problem:
Let
Then
So we can define
nldiffusion_flux! (generic function with 1 method)function nldiffusion_flux!(f,_u, edge) u=unknowns(edge,_u) f[1]=u[1,1]^2-u[1,2]^2end1D Nonlinear diffusion
VoronoiFVM.DenseSystem{Float64,Int32,Int32}(num_species=1)
xxxxxxxxxxnlsystem1d=create_system(grid1d,nldiffusion_flux!,diffusion_source!)Here, Newton's method is used in order to solve the nonlinear system of equations. The Jacobi matrix is assembled from the partial derivatives of the flux function
1×11 Array{Float64,2}:
0.01 0.212368 0.283019 0.324191 0.346554 … 0.324191 0.283019 0.212368 0.016.25
3.12001
1.55008
0.755617
0.342177
0.118959
0.0189612
0.000507516
3.64117e-7
1.87411e-13
xxxxxxxxxx(nlsolution1d,nlhistory1d)=mysolve(nlsystem1d,u_L,u_R)xxxxxxxxxxscalarplot(grid1d,nlsolution1d[1,:],Plotter=PyPlot,resolution=(600,300),title="solution")xxxxxxxxxxlet clf() semilogy(nlhistory1d) title("convergence history") grid() gcf().set_size_inches(6,3) gcf()end2D Nonlinear diffusion
VoronoiFVM.DenseSystem{Float64,Int32,Int32}(num_species=1)
xxxxxxxxxxnlsystem2d=create_system(grid2d,nldiffusion_flux!,diffusion_source!)1×121 Array{Float64,2}:
0.01 0.212368 0.283019 0.324191 0.346554 … 0.324191 0.283019 0.212368 0.016.25
3.12001
1.55008
0.755617
0.342177
0.118959
0.0189612
0.000507516
3.64117e-7
1.87456e-13
xxxxxxxxxx(nlsolution2d,nlhistory2d)=mysolve(nlsystem2d,u_L,u_R,bcl=4, bcr=2)xxxxxxxxxxscalarplot(grid2d,nlsolution2d[1,:],Plotter=PyPlot,resolution=(300,300),fignumber=2,title="solution")Status `/tmp/jl_Vy3imp/Project.toml` [cfc395e8] ExtendableGrids v0.7.4 [5eed8a63] GridVisualize v0.1.2 [7f904dfe] PlutoUI v0.7.1 [d330b81b] PyPlot v2.9.0 [82b139dc] VoronoiFVM v0.10.3