22.9 s
5.0 ms

Extracting integral data from Finite Volume solutions

After calculating solutions based on the finite volume method, it may be interesting to obtain information about the solution besides of the graphical representation.

Here, we focus on the following data:

  • integrals of the solution

  • flux through parts of the boundary

10.4 μs

Sample problem

Here, we define a sample problem for discussing these issues, which could be formulated in a more general way as well.

4.0 μs
make_grid (generic function with 1 method)
45.0 μs
grid
ExtendableGrids.ExtendableGrid{Float64, Int32};
dim: 2 nodes: 631 cells: 1159 bfaces: 101

1.4 s
3.8 s

Let us define the following reaction - diffusion system in Ω:

tu1u1+r(u1,u2)=f=1.0tu2u1r(u1,u2)=0

with boundary conditions u2=0 on Γ2Ω and r(u1,u2)=u1+0.1u2.

The source f creates species u1 which reacts to u2, u2 then leaves the domain at boundary Γ2.

5.2 μs
22.5 μs
24.4 μs
13.9 μs
19.8 μs
14.0 μs

... be careful with the sign: reaction is on the left hand side, source on the right hand side.

2.6 μs

Create the system, enable species, set boundary condition, solve, create initial value:

2.2 μs
physics
VoronoiFVM.Physics(num_species=2, flux=flux, storage=storage, reaction=reaction, source=source, breaction=nofunc2, bstorage=nofunc2, generic_operator=nofunc_generic, generic_operator_sparsity=nofunc_generic_sparsity)
12.0 ms
411 ms
261 ns
inival
2×631 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.0
10.5 ms

Stationary case

2.7 μs

For this problem, we have the following flux balances derived from the equations and from Gauss' theorem:

Ωr(u1,u2)dω=ΩfdωΩr(u1,u2)dω=Γ2u2nds

The volume integrals can be approximated based on the finite volume subdivision Ω=iNωi:

Ωr(u1,u2)dωiN|ωi|r(u1,i,u2,i)ΩfdωiN|ωi|fi

13.1 μs
u
2×631 Matrix{Float64}:
 1.04961   1.04503      1.04503      …  1.0496    1.04956   1.04573  1.04954
 0.647343  3.67642e-32  6.23316e-32     0.646598  0.644086  0.26481  0.642655
2.0 s
1.1 s

The integrate method of VoronoiFVM provides a possibility to calculate the volume integral of a function of a solution as described above. It returns a num_species×num_regions matrix of the integrals of the function of the unknowns over the different subdomains (here, we have only one):

2.6 μs
  • Amount of u1 and u2 in the domain aka integral over identity storage function:

4.5 μs
U
2×1 Matrix{Float64}:
 0.7858573677959029
 0.35857367795902967
16.7 ms
  • Amount of species created by source term per unit time:

3.2 μs
F
2×1 Matrix{Float64}:
 0.7499999999999993
 0.0
5.3 ms
  • Amount of reaction per unit time:

3.3 μs
R
2×1 Matrix{Float64}:
  0.7499999999999992
 -0.7499999999999992
7.2 ms

Reaction == creation ?

2.3 μs

Let us check our first identity: creation rate = reaction rate:

5.7 μs
true
524 ns

Outflow == reaction ?

2.3 μs

The test function trick

This trick goes back to work of H. Gajewski in the field of semiconductor device simulation.

3.3 μs

But what about the boundary integral ? Here, we use a trick to cast the surface integral to a volume integral with the help of a test function:

Let T(x) be the solution of the Laplace problem 2T=0 in Ω and the boundary conditions

T=0atΓ4T=1atΓ2nT=0atΓ1,Γ3

7.0 μs

VoronoiFVM.jl provides a special API for obtaining such a test function:

2.9 μs
1.4 s
154 ms

Write j=u. and assume j+r=f

Γ2jnds=Γ2Tjndsdue toT=1onΓ2=ΩTjndsdue toT=0onΓ4,jn=0onΓ1,Γ3=Ω(Tj)dω(Gauss)=ΩTjdω+ΩTjdω=ΩTjdω+ΩT(fr)dω

and we approximate

ΩTjdωk,l|ωkωl|hk,lg(uk,ul)(TkTl)

where the sum runs over pairs of neigboring control volumes.

4.0 μs

The integrate method with a test function parameter returns a value for each species, the sign convention assumes that species leaving the domain lead to negative values.

2.9 μs
I
11.0 ms

Check that none of u1 leaves the domain through the boundary:

2.5 μs
true
9.3 ms

Check that creation of u2 in the reaction is balanced by u2 leaving the domain through Γ2:

2.6 μs
true
497 ns

So we indeed can confirm the requirement for the right balance of source, reaction and outflow.

2.3 μs

Transient problem

For the transient case, in addition, we need to consider the time derivative part along with reaction and source. In the derivation of the test function procedure, under the assumption of the implicit Euler time discretization method, this can be achieved by handling the finite difference in time along with source and reaction.

3.2 μs
66.0 ns
3.9 ms
118 ns
118 ns
127 ns
120 ns
tsol
t: 52-element Vector{Float64}:
  0.0
  0.05
  0.07624404074558075
  0.10317181117166707
  0.1308175835099931
  0.15921827342132694
  0.18841372976572393
  ⋮
  5.559040374037019
  6.3928478027881015
  7.3928478027881015
  8.3928478027881
  9.3928478027881
 10.0
u: 52-element Vector{Matrix{Float64}}:
 [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
 [0.04762986051262805 0.04762515338868721 … 0.047626533643388674 0.04762983009855026; 0.002333433999389573 2.7293310792136733e-34 … 0.0015109610896880744 0.0023298340140827903]
 [0.07199507932790919 0.07198603534863536 … 0.07198859299349966 0.071995017790104; 0.004173630571335018 4.6191767690938325e-34 … 0.0026298884586591536 0.0041664244297611]
 [0.09634579206667453 0.09632984681193643 … 0.09633412101648231 0.09634567399379049; 0.006676211888525428 6.934873923757612e-34 … 0.004060917377954477 0.006662711969808952]
 [0.1206812680926302 0.12065526905151462 … 0.1206618529370015 0.12068105702750248; 0.009853691310599 9.64290547275173e-34 … 0.005784363860491114 0.009830330601194781]
 [0.1450007114816121 0.14496097925801335 … 0.14497051166089883 0.14500035994329577; 0.013714929631473617 1.2723773752982496e-33 … 0.007788007080055941 0.013677406839114099]
 [0.1693032610197695 0.16924565599166444 … 0.16925881538494889 0.16930271135296024; 0.01826577647204192 1.6165262499841943e-33 … 0.010063941948642876 0.018209229564488182]
 ⋮
 [1.0385752156887353 1.0340921165535901 … 1.03477911038836 1.0385058294133163; 0.6343307920012656 3.6074790509346257e-32 … 0.2597250519725562 0.6297451771316646]
 [1.0433476555389323 1.0388205387820237 … 1.039514018332502 1.04327756408024; 0.6399421547157282 3.637214644036565e-32 … 0.26191803839607647 0.6353124236987555]
 [1.0463385855795477 1.0417837846404365 … 1.0424813426603208 1.046268050548031; 0.6434698397041693 3.655903536946323e-32 … 0.26329645679280594 0.6388123656651705]
 [1.047901640125766 1.0433323388819464 … 1.044032032900378 1.0478308727419585; 0.645317060822444 3.6656880700021267e-32 … 0.2640181652105382 0.6406450566967268]
 [1.0487185330763111 1.0441416427459433 … 1.0448424546229953 1.0486476440787889; 0.6462836845052583 3.670807629433297e-32 … 0.26439579792203355 0.6416040760501582]
 [1.049037582750251 1.0444577261691323 … 1.045158974955603 1.0489666462177778; 0.646661462958075 3.6728083583632383e-32 … 0.26454337989061 0.6419788823648036]
4.6 s

The call to solve corresponds to a new API for transient solutions. It returns a solution object which is compatible to that from DifferentialEquations.jl.

In particular, a TransientSolution tsol can be accessed as follows:

  • tsol[it] contains the solution for timestep i

  • tsol[ispec,:,it] contains the solution for component ispec at timestep i

  • tsol(t) returns a (linearly) interpolated solution value for t.

  • tsol.t[it] is the corresponding time

  • tsol[ispec,ix,it] refers to solution of component ispec at node ix at moment it

9.9 μs

Time: 6.7

32.6 ms
110 ms
14.9 ms

From the solution we now can calculate the normal flux via our test function "trick", once again through the API provided by VoronoiFVM:

2.2 μs
173 ms

For increasing time, the outflow rate should approach the value we calculated from the stationary solution:

2.2 μs
239 ms

The overall amount of species which left the domain is can be calculated integrating the discrete outflow rate over time

Iall=t0tendΓ2u2nds

2.6 μs
6.35637165496992
474 ns

The amount of species created via the source term (measured in F) integrated over time should be equal to the sum of the amount of species left in the domain at the very end of the evolution and the amount of species which left the domain:

t0tendΩfdωdt=Ω(u1+u2)dω+Iall

2.9 μs
Uend
2×1 Matrix{Float64}:
 0.7854274358734347
 0.35820090915664426
9.1 ms
true
408 ns
2.1 μs
      Status `/tmp/jl_9t6uW1/Project.toml`
  [cfc395e8] ExtendableGrids v0.7.4
  [7f904dfe] PlutoUI v0.7.4
  [d330b81b] PyPlot v2.9.0
  [57bfcd06] SimplexGridFactory v0.5.1
  [f7e6ffb2] Triangulate v1.0.1
  [82b139dc] VoronoiFVM v0.10.8
679 ms