VoronoiFVM.jl: Tipps and Examples
Grid generation
VoronoiFVM works on simplicial grids provided by the package ExtendableGrids.jl
There are several ways to create a grid.
1D grids
1D grids are created from a vector of monotonicaly increasing x-axis positions.
0.0
0.05
0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
0.55
0.6
0.65
0.7
0.75
0.8
0.85
0.9
0.95
1.0
xxxxxxxxxx# Create a 1D vector:X=collect(range(0,1,length=21))ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 1 nodes: 21 cells: 20 bfaces: 2
xxxxxxxxxx# Create grid from vector:grid1d_a=ExtendableGrids.simplexgrid(X)xxxxxxxxxx# Visualize gridGridVisualize.gridplot(grid1d_a,resolution=(600,200),Plotter=PyPlot)As we see, the grid is chacracterized by interior points, and boundary points. Each grid cell is endowed with a region number (for allowing different physics, parameters etc. for different regions). Each boundary node has a boundary region number, which is meant to be used to distinguish different boundary conditions.
More sophisticated grids can be created, as we see in the following example:
ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 1 nodes: 53 cells: 52 bfaces: 3
xxxxxxxxxxgrid1d_b=let hmax=0.1 hmin=0.01 # Create vectors with geometric distributions of interval sizes X1=ExtendableGrids.geomspace(0.0,1.0,hmax,hmin) X2=geomspace(1.0,2.0,hmin,hmax) # Glue them together at common point x=1 (this is different from vcat!) X3=glue(X1,X2) grid1d_b=simplexgrid(X3) # Mark an additional interior boundary point at x=1 ExtendableGrids.bfacemask!(grid1d_b,[1.0],[1.0],3) # Change cell region number at the right part ExtendableGrids.cellmask!(grid1d_b,[1.0],[2.0],2) grid1d_bendxxxxxxxxxxgridplot(grid1d_b,resolution=(600,200),Plotter=PyPlot,aspect=0.5)2D Tensor product grids
These are created from two vectors of x and y coordinates, respectively. This results in the creation of a grid of quadrilaterals. Then, each of them is subdivided into two triangles, resulting in a boundary conforming Delaunay grid.
ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 2 nodes: 121 cells: 200 bfaces: 40
xxxxxxxxxxgrid2d_a=let X=collect(range(0,1,length=11)) Y=collect(range(0,1,length=11)) simplexgrid(X,Y)endxxxxxxxxxxgridplot(grid2d_a,resolution=(600,200),Plotter=PyPlot,legend_location=(1.5,0))Once again, we see a default distrbution of cell regions and boundary regions. This can be modified in a similar manner as in the 1D case.
ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 2 nodes: 121 cells: 200 bfaces: 56, edges: 320
xxxxxxxxxxgrid2d_b=let X=collect(range(0,1,length=11)) Y=collect(range(0,1,length=11)) grid=simplexgrid(X,Y) cellmask!(grid,[0.3,0.3],[0.7,0.7],2) bfacemask!(grid,[0.3,0.3],[0.3,0.7],5) bfacemask!(grid,[0.3,0.7],[0.7,0.7],6) bfacemask!(grid,[0.7,0.3],[0.7,0.7],7) bfacemask!(grid,[0.3,0.3],[0.7,0.3],8) gridendxxxxxxxxxxgridplot(grid2d_b,resolution=(600,200),Plotter=PyPlot,legend_location=(1.5,0))2D Unstructured grids
These can be created using the mesh generator Triangle (by J. Shewchuk) via the packages Triangulate.jl and SimplexGridFactory.jl.
builder2d (generic function with 1 method)xxxxxxxxxxfunction builder2d() b=SimplexGridFactory.SimplexGridBuilder(Generator=Triangulate) p1=point!(b,0,0) p2=point!(b,0,1) p3=point!(b,0.5,0) facetregion!(b,1) facet!(b,p1,p2) facetregion!(b,2) facet!(b,p2,p3) facetregion!(b,3) facet!(b,p1,p3) point!(b,0.1,0.1) bendTriangulate
3
1
1.0
1.0e-12
1
2
3
1
2
2
3
1
3
2
1.0e-12
1.79769e308
1.79769e308
-1.79769e308
-1.79769e308
0.01
2×4 ElasticArrays.ElasticMatrix{Float64, 1, Vector{Float64}}:
0.0 0.0 0.5 0.1
0.0 1.0 0.0 0.10×0 Matrix{Vector{Int32}}10
1
2
3
4
5
0.05
0
0
2×0 ElasticArrays.ElasticMatrix{Float64, 1, Vector{Float64}}:optlevel
1
:attributes
true
:quiet
true
:verbose
false
:addflags
""
:maxvolume
Inf
:confdelaunay
true
:unsuitable
nothing
:debugfacets
true
:volumecontrol
true
:quality
true
:flags
nothing
:refine
false
:PLC
true
:nosteiner
false
:minangle
20
:check
false
true
For debugging purposes, the current state of the builder and its possible output can be visualized:
xxxxxxxxxxbuilderplot(builder,Plotter=PyPlot)Finally, we can create a grid from the builder:
ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 2 nodes: 230 cells: 381 bfaces: 77
xxxxxxxxxxgrid2d_c=simplexgrid(builder,maxvolume=0.001)xxxxxxxxxxgridplot(grid2d_c,resolution=(600,200),Plotter=PyPlot,legend_location=(2,0))Stationary scalar problems
Diffusion with Dirichlet boundary conditions
This is mathematically similar to heat conduction and other problems.
Besides of the domain and its boundary it is characterize by a flux term and a source term.
solve_diffproblem_dirichlet (generic function with 1 method)xxxxxxxxxxfunction solve_diffproblem_dirichlet(grid;D=1.0) species1=1 # Use finite difference flux between disretization points. # Division by distance and multiplication by interface size # is done by the VoronoiFVM Module. function flux(f,u0,edge) u=unknowns(edge,u0) f[species1]=D*(u[species1,1]-u[species1,2]) end # Specify a constant source term function source(f,node) f[species1]=10 end # Combine flux and source to "physics" physics=VoronoiFVM.Physics(flux=flux,source=source) # Create system from physics and grid system=VoronoiFVM.System(grid,physics) # Enable species in cellregion 1 enable_species!(system,species1,[1]) # Enable boundary conditions. For those boundary regions # which are not specified here, by default, homogeneous # Neumann boundary conditions are assumed. west=dim_space(grid)==1 ? 1 : 4 east=2 boundary_dirichlet!(system, species1, west, 0) boundary_dirichlet!(system, species1, east, 1) # Solve with given initial value solve(unknowns(system,inival=0),system)end1×21 Matrix{Float64}:
6.0e-30 0.2875 0.55 0.7875 1.0 … 1.6875 1.6 1.4875 1.35 1.1875 1.0xxxxxxxxxxsolution1d_a=solve_diffproblem_dirichlet(grid1d_a)xxxxxxxxxxscalarplot(grid1d_a,solution1d_a[1,:],Plotter=PyPlot)1×121 Matrix{Float64}:
3.0e-31 0.55 1.0 1.35 1.6 1.75 1.8 … 1.6 1.75 1.8 1.75 1.6 1.35 1.0xxxxxxxxxxsolution2d_a=solve_diffproblem_dirichlet(grid2d_a)xxxxxxxxxxscalarplot(grid2d_a,solution2d_a[1,:],Plotter=PyPlot)Diffusion with Robin boundary conditions
solve_diffproblem_robin (generic function with 1 method)xxxxxxxxxxfunction solve_diffproblem_robin(grid;D=1.0,a=0.5) species1=1 function flux(f,u0,edge) u=unknowns(edge,u0) f[species1]=D*(u[species1,1]-u[species1,2]) end function source(f,node) f[species1]=10 end physics=VoronoiFVM.Physics(flux=flux,source=source) system=VoronoiFVM.System(grid,physics) enable_species!(system,species1,[1]) west=dim_space(grid)==1 ? 1 : 4 east=2 boundary_robin!(system, species1, west, a, 0) boundary_robin!(system, species1, east, a, a*1) solve(unknowns(system,inival=0),system)end1×21 Matrix{Float64}:
5.33333 5.5875 5.81667 6.02083 6.2 … 6.4 6.25417 6.08333 5.8875 5.66667xxxxxxxxxxsolution1d_robin=solve_diffproblem_robin(grid1d_a,a=1)xxxxxxxxxxscalarplot(grid1d_a,solution1d_robin[1,:],Plotter=PyPlot)1×121 Matrix{Float64}:
5.33333 5.81667 6.2 6.48333 6.66667 … 6.73333 6.61667 6.4 6.08333 5.66667xxxxxxxxxxsolution2d_robin=solve_diffproblem_robin(grid2d_a,a=1)xxxxxxxxxxscalarplot(grid2d_a,solution2d_robin[1,:],Plotter=PyPlot)Stationary Reaction-Diffusion problem
Here, we regard two species
Boundary conditons not specified are assumed to be homogeneous Neumann.
solve_readiff (generic function with 1 method)xxxxxxxxxxfunction solve_readiff(grid;D_1=1.0,D_2=1.0,k=1) species1=1 species2=2 function flux(f,u0,edge) u=unknowns(edge,u0) f[species1]=D_1*(u[species1,1]-u[species1,2]) f[species2]=D_2*(u[species2,1]-u[species2,2]) end function reaction(f,u0,node) u=unknowns(node,u0) r=k*u[species1] f[species1]=r f[species2]=-r end physics=VoronoiFVM.Physics(num_species=2,flux=flux,reaction=reaction) system=VoronoiFVM.System(grid,physics) enable_species!(system,species1,[1]) enable_species!(system,species2,[1]) west=dim_space(grid)==1 ? 1 : 4 east=2 boundary_dirichlet!(system, species1, west,1) boundary_dirichlet!(system, species2, east,0) solve(unknowns(system,inival=0),system)end2×21 Matrix{Float64}:
1.0 0.854464 0.730289 0.624372 … 0.0890498 0.0858439 0.0847841
2.24551 2.23301 2.19915 2.14703 0.311807 0.156976 3.16072e-30xxxxxxxxxxsolution_readiff_1d=solve_readiff(grid1d_a,k=10, D_2=1)xxxxxxxxxxlet v=GridVisualizer(Plotter=PyPlot) scalarplot!(v[1,1],grid1d_a, solution_readiff_1d[1,:],label="spec1", color=:red) scalarplot!(v[1,1],grid1d_a, solution_readiff_1d[2,:],label="spec2", color=:green,show=true,clear=false)end2×121 Matrix{Float64}:
1.0 0.884085 0.785851 0.703335 0.634885 … 0.478053 0.464174 0.459578
0.71873 0.70873 0.681048 0.63765 0.580184 0.233355 0.121319 6.29576e-32xxxxxxxxxxsolution_readiff_2d=solve_readiff(grid2d_a,k=2)xxxxxxxxxxlet v=GridVisualizer(Plotter=PyPlot,layout=(1,2)) scalarplot!(v[1,1],grid2d_a, solution_readiff_2d[1,:],label="spec1",flimits=(0,1)) scalarplot!(v[1,2],grid2d_a, solution_readiff_2d[2,:],label="spec2",flimits=(0,1), show=true)endTransient Reaction-Diffusion problem
Here, we regard two species
Boundary conditons not specified are assumed to be homogeneous Neumann.
evolution (generic function with 1 method)xxxxxxxxxx# Function describing evolution of system with initial value inival # using the Implicit Euler methodfunction evolution(inival, # initial value sys, # finite volume system grid, # simplex grid tstep, # initial time step tend, # end time dtgrowth # time step growth factor ) time=0.0 # record time and solution times=[time] solutions=[copy(inival)] solution=copy(inival) while time<tend time=time+tstep solve!(solution,inival,sys,tstep=tstep) # solve implicit Euler time step inival.=solution # copy solution to inivalue push!(times,time) push!(solutions,copy(solution)) tstep*=dtgrowth # increase timestep by factor when approaching stationary state end # return result and grid (times=times,solutions=solutions,grid=grid)endtransient_reaction_diffusion (generic function with 1 method)xxxxxxxxxxfunction transient_reaction_diffusion(grid;D_1=1.0,D_2=1.0,k=1, tstep=1.0e-3,tend=1,dtgrowth=1.1) species1=1 species2=2 function flux(f,u0,edge) u=unknowns(edge,u0) f[species1]=D_1*(u[species1,1]-u[species1,2]) f[species2]=D_2*(u[species2,1]-u[species2,2]) end function reaction(f,u0,node) u=unknowns(node,u0) r=k*u[species1] f[species1]=r f[species2]=-r end function storage(f,u,node) f.=u end physics=VoronoiFVM.Physics(num_species=2,flux=flux,reaction=reaction,storage=storage) system=VoronoiFVM.System(grid,physics) enable_species!(system,species1,[1]) enable_species!(system,species2,[1]) west=dim_space(grid)==1 ? 1 : 4 east=2 boundary_dirichlet!(system, species1, west,1) boundary_dirichlet!(system, species2, east,0) ## Create a solution array inival=unknowns(system,inival=0) evolution(inival,system,grid,tstep,tend,dtgrowth) end0.0
0.001
0.0021
0.00331
0.004641
0.0061051
0.00771561
0.00948717
0.0114359
0.0135795
0.0159374
0.0185312
0.0213843
0.0245227
0.027975
0.0317725
0.0359497
0.0405447
0.0455992
0.0511591
43.8993
48.2902
53.1202
58.4332
64.2776
70.7063
77.778
85.5568
94.1134
103.526
2×21 Matrix{Float64}:
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.02×21 Matrix{Float64}:
1.0 0.23429 0.0548919 … 4.53819e-12 1.11825e-12 4.96724e-13
0.00069226 0.000307586 0.00010615 5.37779e-14 1.25719e-14 2.63856e-432×21 Matrix{Float64}:
1.0 0.388729 0.129427 … 9.70382e-11 2.62235e-11 1.25317e-11
0.00131875 0.000780668 0.000345951 1.26334e-12 3.17705e-13 6.6674e-422×21 Matrix{Float64}:
1.0 0.493864 0.206185 … 1.06107e-9 3.13559e-10 1.60499e-10
0.00195214 0.00135646 0.000715781 1.51357e-11 4.07663e-12 8.55451e-412×21 Matrix{Float64}:
1.0 0.568244 0.277615 … 7.89166e-9 2.543e-9 1.38824e-9
0.00262716 0.0020111 0.00120404 1.23024e-10 3.53349e-11 7.41403e-402×21 Matrix{Float64}:
1.0 0.623046 0.341224 … 4.48229e-8 1.57063e-8 9.10588e-9
0.00336164 0.00273872 0.00180061 7.6171e-10 2.32314e-10 4.87393e-392×21 Matrix{Float64}:
1.0 0.665021 0.396862 … 2.0705e-7 7.8674e-8 4.82398e-8
0.00416662 0.0035414 0.00249964 3.82598e-9 1.23393e-9 2.58846e-382×21 Matrix{Float64}:
1.0 0.6983 0.445307 … 8.09271e-7 3.32497e-7 2.14744e-7
0.00505087 0.00442479 0.0032996 1.62192e-8 5.50887e-9 1.15546e-372×21 Matrix{Float64}:
1.0 0.725463 0.487589 0.305176 … 2.75049e-6 1.21828e-6 8.25489e-7
0.00602284 0.0053963 0.00420244 0.00294787 5.96309e-8 2.12446e-8 4.4553e-372×21 Matrix{Float64}:
1.0 0.748172 0.5247 … 8.29339e-6 3.94783e-6 2.79554e-6
0.00709136 0.00646445 0.00521286 1.93965e-7 7.22023e-8 1.51393e-362×21 Matrix{Float64}:
1.0 0.767529 0.557499 … 2.25305e-5 1.14884e-5 8.46976e-6
0.00826603 0.00763874 0.00633768 5.66815e-7 2.19619e-7 4.60412e-362×21 Matrix{Float64}:
1.0 0.784289 0.586693 … 5.58339e-5 3.03906e-5 2.32422e-5
0.00955732 0.00892964 0.00758547 1.50636e-6 6.05297e-7 1.2687e-352×21 Matrix{Float64}:
1.0 0.798987 0.612852 … 0.000127507 7.38152e-5 5.83576e-5
0.0109767 0.0103486 0.00896638 3.67743e-6 1.52712e-6 3.20013e-352×21 Matrix{Float64}:
1.0 0.812014 0.636436 0.481235 … 0.000270654 0.000166012 0.000135227
0.0125369 0.0119083 0.010492 0.00869996 8.31701e-6 3.55739e-6 7.45284e-352×21 Matrix{Float64}:
1.0 0.823661 0.657814 0.509094 … 0.000537948 0.000348231 0.000291341
0.0142516 0.0136224 0.0121755 0.010303 1.75533e-5 7.70879e-6 1.61459e-342×21 Matrix{Float64}:
1.0 0.834148 0.677286 0.534937 … 0.00100763 0.000685612 0.000587419
0.016136 0.0155062 0.0140313 0.0120849 3.47922e-5 1.56418e-5 3.27522e-342×21 Matrix{Float64}:
1.0 0.84365 0.695096 0.558939 … 0.00178873 0.00127411 0.00111488
0.0182066 0.0175763 0.0160757 0.0140608 6.5131e-5 2.98935e-5 6.25741e-342×21 Matrix{Float64}:
1.0 0.852303 0.711445 0.581259 … 0.00302446 0.00224611 0.00200222
0.0204818 0.0198507 0.0183264 0.0162479 0.000115737 5.40928e-5 1.13191e-332×21 Matrix{Float64}:
1.0 0.860217 0.726498 0.602042 … 0.00489262 0.00377326 0.00341869
0.0229814 0.0223495 0.020803 0.0186653 0.000196115 9.3122e-5 1.94791e-332×21 Matrix{Float64}:
1.0 0.867481 0.740397 0.621414 … 0.00760248 0.00606525 0.00557377
0.0257271 0.0250944 0.0235272 0.021334 0.000318206 0.000153182 3.20298e-332×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-312×21 Matrix{Float64}:
1.0 0.963161 0.928729 0.896619 … 0.651348 0.648916 0.648106
0.409894 0.408644 0.404986 0.399006 0.0729363 0.0372793 7.61788e-31ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 1 nodes: 21 cells: 20 bfaces: 2
xxxxxxxxxxtsol_readiff=transient_reaction_diffusion(grid1d_a,k=1,tend=100)time=
xxxxxxxxxxlet vis=GridVisualizer(layout=(1,2),resolution=(600,300),Plotter=PyPlot) scalarplot!(vis[1,1],tsol_readiff.grid, tsol_readiff.solutions[t_readiff][1,:], title="u1: t=$(tsol_readiff.times[t_readiff])", flimits=(0,1),colormap=:cool,levels=50,clear=true) scalarplot!(vis[1,2],tsol_readiff.grid, tsol_readiff.solutions[t_readiff][2,:], title="u2: t=$(tsol_readiff.times[t_readiff])", flimits=(0,1),colormap=:cool,levels=50,show=true)endxxxxxxxxxxTableOfContents()xxxxxxxxxxbegin ENV["LANG"]="C" using Pkg Pkg.activate(mktempdir()) Pkg.add(["PyPlot","PlutoUI","ExtendableGrids","SimplexGridFactory","VoronoiFVM","GridVisualize","Triangulate"]) using PlutoUI,PyPlot,ExtendableGrids,SimplexGridFactory,VoronoiFVM,GridVisualize,Triangulate PyPlot.svg(true)end;Status `/tmp/jl_SKqLWP/Project.toml` [cfc395e8] ExtendableGrids v0.7.4 [5eed8a63] GridVisualize v0.1.3 [7f904dfe] PlutoUI v0.7.2 [d330b81b] PyPlot v2.9.0 [57bfcd06] SimplexGridFactory v0.5.1 [f7e6ffb2] Triangulate v1.0.1 [82b139dc] VoronoiFVM v0.10.5